meta.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // Template metaprogramming support
  2. //
  3. // Platform: ISO C++ 98/11
  4. // $Id$
  5. //
  6. // (c) __vic 2011
  7. #ifndef __VIC_META_H
  8. #define __VIC_META_H
  9. #include<__vic/defs.h>
  10. #if __cplusplus >= 201103L && !defined(__VIC_HAVE_TYPE_TRAITS)
  11. #define __VIC_HAVE_TYPE_TRAITS 1
  12. #endif
  13. #ifdef __VIC_HAVE_TYPE_TRAITS
  14. #include<type_traits>
  15. #endif
  16. namespace __vic {
  17. #ifdef __VIC_HAVE_TYPE_TRAITS
  18. //----------------------------------------------------------------------------
  19. using std::integral_constant;
  20. using std::true_type;
  21. using std::false_type;
  22. using std::is_same;
  23. using std::is_const;
  24. using std::remove_const;
  25. using std::remove_volatile;
  26. using std::remove_cv;
  27. using std::remove_reference;
  28. using std::remove_pointer;
  29. using std::enable_if;
  30. //----------------------------------------------------------------------------
  31. #else // no <type_traits>
  32. //////////////////////////////////////////////////////////////////////////////
  33. // Convenient template for integral constant types
  34. template<class T, T Val>
  35. struct integral_constant
  36. {
  37. typedef T value_type;
  38. typedef integral_constant<T, Val> type;
  39. static const T value = Val;
  40. };
  41. //////////////////////////////////////////////////////////////////////////////
  42. typedef integral_constant<bool, true> true_type;
  43. typedef integral_constant<bool, false> false_type;
  44. //----------------------------------------------------------------------------
  45. template<class T1, class T2> struct is_same : false_type {};
  46. template<class T> struct is_same<T,T> : true_type {};
  47. //----------------------------------------------------------------------------
  48. template<class T> struct is_const : false_type {};
  49. template<class T> struct is_const<const T> : true_type {};
  50. //----------------------------------------------------------------------------
  51. template<class T> struct remove_const { typedef T type; };
  52. template<class T> struct remove_const<const T> { typedef T type; };
  53. //----------------------------------------------------------------------------
  54. template<class T> struct remove_volatile { typedef T type; };
  55. template<class T> struct remove_volatile<volatile T> { typedef T type; };
  56. //----------------------------------------------------------------------------
  57. template<class T> struct remove_cv
  58. {
  59. typedef typename remove_const<
  60. typename remove_volatile<T>::type>::type type;
  61. };
  62. //----------------------------------------------------------------------------
  63. template<class T> struct remove_reference { typedef T type; };
  64. template<class T> struct remove_reference<T &> { typedef T type; };
  65. #if __cpp_rvalue_references
  66. template<class T> struct remove_reference<T &&> { typedef T type; };
  67. #endif
  68. //----------------------------------------------------------------------------
  69. template<class T> struct remove_pointer { typedef T type; };
  70. template<class T> struct remove_pointer<T *> { typedef T type; };
  71. //----------------------------------------------------------------------------
  72. template<bool Test, class T = void>
  73. struct enable_if
  74. {
  75. typedef T type;
  76. };
  77. template<class T>
  78. struct enable_if<false, T> {};
  79. //----------------------------------------------------------------------------
  80. #endif // __VIC_HAVE_TYPE_TRAITS
  81. //----------------------------------------------------------------------------
  82. template<class T> struct is_signed_integer : false_type {};
  83. template<> struct is_signed_integer<__VIC_LONGLONG> : true_type {};
  84. template<> struct is_signed_integer<long> : true_type {};
  85. template<> struct is_signed_integer<int> : true_type {};
  86. template<> struct is_signed_integer<short> : true_type {};
  87. template<> struct is_signed_integer<signed char> : true_type {};
  88. template<class T> struct is_unsigned_integer : false_type {};
  89. template<> struct is_unsigned_integer<unsigned __VIC_LONGLONG> : true_type {};
  90. template<> struct is_unsigned_integer<unsigned long> : true_type {};
  91. template<> struct is_unsigned_integer<unsigned int> : true_type {};
  92. template<> struct is_unsigned_integer<unsigned short> : true_type {};
  93. template<> struct is_unsigned_integer<unsigned char> : true_type {};
  94. //----------------------------------------------------------------------------
  95. template<bool Test, class T = void>
  96. struct disable_if : enable_if<!Test, T> {};
  97. //----------------------------------------------------------------------------
  98. template<class T> struct remove_cvref
  99. {
  100. typedef typename remove_cv<
  101. typename remove_reference<T>::type>::type type;
  102. };
  103. //----------------------------------------------------------------------------
  104. #if __cpp_alias_templates
  105. template<class T> using remove_const_t = typename remove_const<T>::type;
  106. template<class T> using remove_volatile_t = typename remove_volatile<T>::type;
  107. template<class T> using remove_cv_t = typename remove_cv<T>::type;
  108. template<class T> using remove_reference_t = typename remove_reference<T>::type;
  109. template<class T> using remove_cvref_t = typename remove_cvref<T>::type;
  110. template<class T> using remove_pointer_t = typename remove_pointer<T>::type;
  111. // No alias for enable_if because in C++11 SFINAE is not guaranteed
  112. #endif
  113. //----------------------------------------------------------------------------
  114. #if __cplusplus >= 201402L // C++14
  115. using std::index_sequence;
  116. using std::make_index_sequence;
  117. #elif __cpp_variadic_templates && __cpp_alias_templates
  118. //////////////////////////////////////////////////////////////////////////////
  119. template<size_t... I>
  120. struct index_sequence
  121. {
  122. static constexpr size_t size() { return sizeof...(I); }
  123. };
  124. //////////////////////////////////////////////////////////////////////////////
  125. // O(log N) implementation from here:
  126. // http://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence
  127. template<typename Seq1, typename Seq2>
  128. struct concat_sequence_;
  129. template<size_t... I1, size_t... I2>
  130. struct concat_sequence_<index_sequence<I1...>, index_sequence<I2...>>
  131. {
  132. using type = index_sequence<I1..., (sizeof...(I1) + I2)...>;
  133. };
  134. //////////////////////////////////////////////////////////////////////////////
  135. template<size_t Size>
  136. struct make_index_sequence_ : concat_sequence_<
  137. typename make_index_sequence_<Size/2>::type,
  138. typename make_index_sequence_<Size - Size/2>::type
  139. >{};
  140. template<> struct make_index_sequence_<0> { using type = index_sequence<>; };
  141. template<> struct make_index_sequence_<1> { using type = index_sequence<0>; };
  142. //////////////////////////////////////////////////////////////////////////////
  143. template<size_t Size>
  144. using make_index_sequence = typename make_index_sequence_<Size>::type;
  145. #endif
  146. //----------------------------------------------------------------------------
  147. } // namespace
  148. #endif // header guard