#include <type_traits>
#include <iterator>
// Do NOT define key_type YET (note the "basic" in the name).
template<class R>
struct range_basic_type_traits
{
// "iterator": The type of the iterators of a range
using iterator = decltype(std::begin(std::declval<R>()));
// "value_type": The type of the values of a range
using value_type = typename std::remove_reference<decltype(*(std::declval<iterator>()))>::type;
};
// Define a "has_key" type (std::true/false_type) for the existence member functions (not checking their return value)
struct _test_has_key {
template<class TARGET> static auto test(TARGET* p) -> decltype(p->key(), std::true_type());
template<class> static auto test(...) -> std::false_type;
};
template<class TARGET> struct has_key : public decltype(_test_has_key::test<TARGET>(0)) {};
// Adding the key_type if the iterator of R has key() defined
template<class R>
struct range_type_traits : public range_basic_type_traits<R>
{
using key_type = typename std::enable_if<
has_key<typename range_basic_type_traits<R>::iterator>::value,
typename std::remove_reference<decltype(std::declval<typename range_basic_type_traits<R>::iterator>().key())>
>::type;
};
//------------------------------------------------------------------------------
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+CgovLyBEbyBOT1QgZGVmaW5lIGtleV90eXBlIFlFVCAobm90ZSB0aGUgImJhc2ljIiBpbiB0aGUgbmFtZSkuCnRlbXBsYXRlPGNsYXNzIFI+CnN0cnVjdCByYW5nZV9iYXNpY190eXBlX3RyYWl0cwp7CiAgICAvLyAiaXRlcmF0b3IiOiBUaGUgdHlwZSBvZiB0aGUgaXRlcmF0b3JzIG9mIGEgcmFuZ2UKICAgIHVzaW5nIGl0ZXJhdG9yID0gZGVjbHR5cGUoc3RkOjpiZWdpbihzdGQ6OmRlY2x2YWw8Uj4oKSkpOwoKICAgIC8vICJ2YWx1ZV90eXBlIjogVGhlIHR5cGUgb2YgdGhlIHZhbHVlcyBvZiBhIHJhbmdlCiAgICB1c2luZyB2YWx1ZV90eXBlID0gdHlwZW5hbWUgc3RkOjpyZW1vdmVfcmVmZXJlbmNlPGRlY2x0eXBlKCooc3RkOjpkZWNsdmFsPGl0ZXJhdG9yPigpKSk+Ojp0eXBlOwp9OwoKCi8vIERlZmluZSBhICJoYXNfa2V5IiB0eXBlIChzdGQ6OnRydWUvZmFsc2VfdHlwZSkgZm9yIHRoZSBleGlzdGVuY2UgbWVtYmVyIGZ1bmN0aW9ucyAobm90IGNoZWNraW5nIHRoZWlyIHJldHVybiB2YWx1ZSkKc3RydWN0IF90ZXN0X2hhc19rZXkgewogICAgdGVtcGxhdGU8Y2xhc3MgVEFSR0VUPiBzdGF0aWMgYXV0byB0ZXN0KFRBUkdFVCogcCkgLT4gZGVjbHR5cGUocC0+a2V5KCksIHN0ZDo6dHJ1ZV90eXBlKCkpOwogICAgdGVtcGxhdGU8Y2xhc3M+ICAgICAgICBzdGF0aWMgYXV0byB0ZXN0KC4uLikgLT4gc3RkOjpmYWxzZV90eXBlOwp9Owp0ZW1wbGF0ZTxjbGFzcyBUQVJHRVQ+IHN0cnVjdCBoYXNfa2V5IDogcHVibGljIGRlY2x0eXBlKF90ZXN0X2hhc19rZXk6OnRlc3Q8VEFSR0VUPigwKSkge307CgoKLy8gQWRkaW5nIHRoZSBrZXlfdHlwZSBpZiB0aGUgaXRlcmF0b3Igb2YgUiBoYXMga2V5KCkgZGVmaW5lZAp0ZW1wbGF0ZTxjbGFzcyBSPgpzdHJ1Y3QgcmFuZ2VfdHlwZV90cmFpdHMgOiBwdWJsaWMgcmFuZ2VfYmFzaWNfdHlwZV90cmFpdHM8Uj4KewogICAgdXNpbmcga2V5X3R5cGUgPSB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjwKICAgICAgICBoYXNfa2V5PHR5cGVuYW1lIHJhbmdlX2Jhc2ljX3R5cGVfdHJhaXRzPFI+OjppdGVyYXRvcj46OnZhbHVlLAogICAgICAgIHR5cGVuYW1lIHN0ZDo6cmVtb3ZlX3JlZmVyZW5jZTxkZWNsdHlwZShzdGQ6OmRlY2x2YWw8dHlwZW5hbWUgcmFuZ2VfYmFzaWNfdHlwZV90cmFpdHM8Uj46Oml0ZXJhdG9yPigpLmtleSgpKT4KICAgID46OnR5cGU7Cn07CgoKLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCnRlbXBsYXRlPGNsYXNzIEssIGNsYXNzIFQ+CnN0cnVjdCBUZXN0IHsKICAgIHN0cnVjdCBpdGVyYXRvciB7CiAgICAgICAgY29uc3QgVCAmICBvcGVyYXRvciooKSBjb25zdDsKICAgICAgICBjb25zdCBLICYgIGtleSgpIGNvbnN0OwogICAgfTsKICAgIGl0ZXJhdG9yIGJlZ2luKCkgY29uc3Q7Cn07CgppbnQgbWFpbigpCnsKICAgIC8vIHRlc3QgaXQ6CiAgICB1c2luZyBLID0gaW50OwogICAgdXNpbmcgVCA9IGZsb2F0OwogICAgdXNpbmcgUiA9IFRlc3Q8SyxUPjsKICAgIHN0YXRpY19hc3NlcnQoc3RkOjppc19zYW1lPHR5cGVuYW1lIHJhbmdlX3R5cGVfdHJhaXRzPFI+Ojp2YWx1ZV90eXBlLCBjb25zdCBUPjo6dmFsdWUsICJ2YWx1ZV90eXBlIGlzIGluY29ycmVjdCIpOwogICAgc3RhdGljX2Fzc2VydChzdGQ6OmlzX3NhbWU8dHlwZW5hbWUgcmFuZ2VfdHlwZV90cmFpdHM8Uj46OmtleV90eXBlLCBjb25zdCBLPjo6dmFsdWUsICJrZXlfdHlwZSBpcyBpbmNvcnJlY3QiKTsKfQ==