fork download
  1. #include <type_traits>
  2. #include <iterator>
  3.  
  4. template<class R>
  5. struct range_basic_type_traits
  6. {
  7. // "iterator": The type of the const iterators of a range
  8. using iterator = decltype(std::begin(std::declval<R const>()));
  9.  
  10. // "value_type": The (non-reference) type of the values of a range
  11. using value_type = typename std::remove_reference<decltype(*(std::declval<iterator>()))>::type;
  12. };
  13.  
  14.  
  15. template<typename R, typename = int> struct maybe_key_type {
  16. // no "key_type" defined.
  17. };
  18. template<typename R> struct maybe_key_type<R, decltype(std::declval<typename range_basic_type_traits<R>::iterator const>().key(), 0)> {
  19. // Add support for "key_type":
  20. using key_type = typename std::remove_reference<decltype(std::declval<typename range_basic_type_traits<R>::iterator const>().key())>::type;
  21. };
  22.  
  23.  
  24. // Putting things together:
  25. template<class R>
  26. struct range_type_traits : public range_basic_type_traits<R>, public maybe_key_type<R>
  27. {
  28. };
  29.  
  30.  
  31. //------------------------------------------------------------------------------
  32.  
  33. template<class K, class T>
  34. struct Test {
  35. struct iterator {
  36. const T & operator*() const;
  37. const K & key() const;
  38. };
  39. iterator begin() const;
  40. };
  41.  
  42. int main()
  43. {
  44. // test it:
  45. using K = int;
  46. using T = float;
  47. using R = Test<K,T>;
  48. static_assert(std::is_same<typename range_type_traits<R>::value_type, const T>::value, "value_type is incorrect");
  49. static_assert(std::is_same<typename range_type_traits<R>::key_type, const K>::value, "key_type is incorrect");
  50. }
Success #stdin #stdout 0s 2892KB
stdin
Standard input is empty
stdout
Standard output is empty