fork download
  1. #include <type_traits>
  2. #include <iterator>
  3.  
  4. // Do NOT define key_type YET (note the "basic" in the name).
  5. template<class R>
  6. struct range_basic_type_traits
  7. {
  8. // "iterator": The type of the iterators of a range
  9. using iterator = decltype(std::begin(std::declval<R>()));
  10.  
  11. // "value_type": The type of the values of a range
  12. using value_type = typename std::remove_reference<decltype(*(std::declval<iterator>()))>::type;
  13. };
  14.  
  15.  
  16. // Define a "has_key" type (std::true/false_type) for the existence member functions (not checking their return value)
  17. struct _test_has_key {
  18. template<class TARGET> static auto test(TARGET* p) -> decltype(p->key(), std::true_type());
  19. template<class> static auto test(...) -> std::false_type;
  20. };
  21. template<class TARGET> struct has_key : public decltype(_test_has_key::test<TARGET>(0)) {};
  22.  
  23.  
  24. // Adding the key_type if the iterator of R has key() defined
  25. template<class R>
  26. struct range_type_traits : public range_basic_type_traits<R>
  27. {
  28. using key_type = typename std::enable_if<
  29. has_key<typename range_basic_type_traits<R>::iterator>::value,
  30. typename std::remove_reference<decltype(std::declval<typename range_basic_type_traits<R>::iterator>().key())>
  31. >::type;
  32. };
  33.  
  34.  
  35. //------------------------------------------------------------------------------
  36.  
  37. template<class K, class T>
  38. struct Test {
  39. struct iterator {
  40. const T & operator*() const;
  41. const K & key() const;
  42. };
  43. iterator begin() const;
  44. };
  45.  
  46. int main()
  47. {
  48. // test it:
  49. using K = int;
  50. using T = float;
  51. using R = Test<K,T>;
  52. static_assert(std::is_same<typename range_type_traits<R>::value_type, const T>::value, "value_type is incorrect");
  53. static_assert(std::is_same<typename range_type_traits<R>::key_type, const K>::value, "key_type is incorrect");
  54. }
Compilation error #stdin compilation error #stdout 0s 2892KB
stdin
Standard input is empty
compilation info
prog.cpp: In function ‘int main()’:
prog.cpp:53:5: error: static assertion failed: key_type is incorrect
stdout
Standard output is empty