#include <type_traits>
#include <iterator>
template<class R>
struct range_basic_type_traits
{
// "iterator": The type of the const iterators of a range
using iterator = decltype(std::begin(std::declval<R const>()));
// "value_type": The (non-reference) type of the values of a range
using value_type = typename std::remove_reference<decltype(*(std::declval<iterator>()))>::type;
};
template<typename R, typename = int> struct maybe_key_type {
// no "key_type" defined.
};
template<typename R> struct maybe_key_type<R, decltype(std::declval<typename range_basic_type_traits<R>::iterator const>().key(), 0)> {
// Add support for "key_type":
using key_type = typename std::remove_reference<decltype(std::declval<typename range_basic_type_traits<R>::iterator const>().key())>::type;
};
// Putting things together:
template<class R>
struct range_type_traits : public range_basic_type_traits<R>, public maybe_key_type<R>
{
};
//------------------------------------------------------------------------------
template<class K, class T>
struct Test {
struct iterator {
const T & operator*() const;
const K & key() const;
};
iterator begin() const;
};
int main()
{
// test it:
using K = int;
using T = float;
using R = Test<K,T>;
static_assert(std::is_same<typename range_type_traits<R>::value_type, const T>::value, "value_type is incorrect");
static_assert(std::is_same<typename range_type_traits<R>::key_type, const K>::value, "key_type is incorrect");
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8aXRlcmF0b3I+Cgp0ZW1wbGF0ZTxjbGFzcyBSPgpzdHJ1Y3QgcmFuZ2VfYmFzaWNfdHlwZV90cmFpdHMKewogICAgLy8gIml0ZXJhdG9yIjogVGhlIHR5cGUgb2YgdGhlIGNvbnN0IGl0ZXJhdG9ycyBvZiBhIHJhbmdlCiAgICB1c2luZyBpdGVyYXRvciA9IGRlY2x0eXBlKHN0ZDo6YmVnaW4oc3RkOjpkZWNsdmFsPFIgY29uc3Q+KCkpKTsKCiAgICAvLyAidmFsdWVfdHlwZSI6IFRoZSAobm9uLXJlZmVyZW5jZSkgdHlwZSBvZiB0aGUgdmFsdWVzIG9mIGEgcmFuZ2UKICAgIHVzaW5nIHZhbHVlX3R5cGUgPSB0eXBlbmFtZSBzdGQ6OnJlbW92ZV9yZWZlcmVuY2U8ZGVjbHR5cGUoKihzdGQ6OmRlY2x2YWw8aXRlcmF0b3I+KCkpKT46OnR5cGU7Cn07CgoKdGVtcGxhdGU8dHlwZW5hbWUgUiwgdHlwZW5hbWUgPSBpbnQ+IHN0cnVjdCBtYXliZV9rZXlfdHlwZSB7CiAgICAvLyBubyAia2V5X3R5cGUiIGRlZmluZWQuCn07CnRlbXBsYXRlPHR5cGVuYW1lIFI+IHN0cnVjdCBtYXliZV9rZXlfdHlwZTxSLCBkZWNsdHlwZShzdGQ6OmRlY2x2YWw8dHlwZW5hbWUgcmFuZ2VfYmFzaWNfdHlwZV90cmFpdHM8Uj46Oml0ZXJhdG9yIGNvbnN0PigpLmtleSgpLCAwKT4gewogICAgLy8gQWRkIHN1cHBvcnQgZm9yICJrZXlfdHlwZSI6CiAgICB1c2luZyBrZXlfdHlwZSA9IHR5cGVuYW1lIHN0ZDo6cmVtb3ZlX3JlZmVyZW5jZTxkZWNsdHlwZShzdGQ6OmRlY2x2YWw8dHlwZW5hbWUgcmFuZ2VfYmFzaWNfdHlwZV90cmFpdHM8Uj46Oml0ZXJhdG9yIGNvbnN0PigpLmtleSgpKT46OnR5cGU7Cn07CgoKLy8gUHV0dGluZyB0aGluZ3MgdG9nZXRoZXI6CnRlbXBsYXRlPGNsYXNzIFI+CnN0cnVjdCByYW5nZV90eXBlX3RyYWl0cyA6IHB1YmxpYyByYW5nZV9iYXNpY190eXBlX3RyYWl0czxSPiwgcHVibGljIG1heWJlX2tleV90eXBlPFI+CnsKfTsKCgovLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKdGVtcGxhdGU8Y2xhc3MgSywgY2xhc3MgVD4Kc3RydWN0IFRlc3QgewogICAgc3RydWN0IGl0ZXJhdG9yIHsKICAgICAgICBjb25zdCBUICYgIG9wZXJhdG9yKigpIGNvbnN0OwogICAgICAgIGNvbnN0IEsgJiAga2V5KCkgY29uc3Q7CiAgICB9OwogICAgaXRlcmF0b3IgYmVnaW4oKSBjb25zdDsKfTsKCmludCBtYWluKCkKewogICAgLy8gdGVzdCBpdDoKICAgIHVzaW5nIEsgPSBpbnQ7CiAgICB1c2luZyBUID0gZmxvYXQ7CiAgICB1c2luZyBSID0gVGVzdDxLLFQ+OwogICAgc3RhdGljX2Fzc2VydChzdGQ6OmlzX3NhbWU8dHlwZW5hbWUgcmFuZ2VfdHlwZV90cmFpdHM8Uj46OnZhbHVlX3R5cGUsIGNvbnN0IFQ+Ojp2YWx1ZSwgInZhbHVlX3R5cGUgaXMgaW5jb3JyZWN0Iik7CiAgICBzdGF0aWNfYXNzZXJ0KHN0ZDo6aXNfc2FtZTx0eXBlbmFtZSByYW5nZV90eXBlX3RyYWl0czxSPjo6a2V5X3R5cGUsIGNvbnN0IEs+Ojp2YWx1ZSwgImtleV90eXBlIGlzIGluY29ycmVjdCIpOwp9