type_traits.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. // Template metaprogramming support
  2. //
  3. // Platform: ISO C++ 98/11
  4. // $Id$
  5. //
  6. // (c) __vic 2011
  7. #ifndef __VIC_TYPE_TRAITS_H
  8. #define __VIC_TYPE_TRAITS_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. #include<utility> // for std::index_sequence
  16. #endif
  17. namespace __vic {
  18. #ifdef __VIC_HAVE_TYPE_TRAITS
  19. //----------------------------------------------------------------------------
  20. using std::integral_constant;
  21. using std::true_type;
  22. using std::false_type;
  23. using std::is_same;
  24. using std::is_const;
  25. using std::remove_const;
  26. using std::remove_volatile;
  27. using std::remove_cv;
  28. using std::remove_reference;
  29. using std::remove_pointer;
  30. using std::conditional;
  31. using std::enable_if;
  32. //----------------------------------------------------------------------------
  33. #if __cpp_lib_logical_traits
  34. using std::conjunction;
  35. using std::disjunction;
  36. using std::negation;
  37. #elif __cpp_variadic_templates
  38. //----------------------------------------------------------------------------
  39. template<class...> struct conjunction : true_type {};
  40. template<class B1> struct conjunction<B1> : B1 {};
  41. template<class B1, class... Bn> struct conjunction<B1, Bn...> :
  42. conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
  43. //----------------------------------------------------------------------------
  44. template<class...> struct disjunction : false_type {};
  45. template<class B1> struct disjunction<B1> : B1 {};
  46. template<class B1, class... Bn> struct disjunction<B1, Bn...> :
  47. conditional<bool(B1::value), B1, disjunction<Bn...>>::type {};
  48. //----------------------------------------------------------------------------
  49. #endif
  50. //----------------------------------------------------------------------------
  51. #else // no <type_traits>
  52. //////////////////////////////////////////////////////////////////////////////
  53. // Convenient template for integral constant types
  54. template<class T, T Val>
  55. struct integral_constant
  56. {
  57. typedef T value_type;
  58. typedef integral_constant<T, Val> type;
  59. static const T value = Val;
  60. };
  61. //////////////////////////////////////////////////////////////////////////////
  62. typedef integral_constant<bool, true> true_type;
  63. typedef integral_constant<bool, false> false_type;
  64. //----------------------------------------------------------------------------
  65. template<class T1, class T2> struct is_same : false_type {};
  66. template<class T> struct is_same<T,T> : true_type {};
  67. //----------------------------------------------------------------------------
  68. template<class T> struct is_const : false_type {};
  69. template<class T> struct is_const<const T> : true_type {};
  70. //----------------------------------------------------------------------------
  71. template<class T> struct remove_const { typedef T type; };
  72. template<class T> struct remove_const<const T> { typedef T type; };
  73. //----------------------------------------------------------------------------
  74. template<class T> struct remove_volatile { typedef T type; };
  75. template<class T> struct remove_volatile<volatile T> { typedef T type; };
  76. //----------------------------------------------------------------------------
  77. template<class T> struct remove_cv
  78. {
  79. typedef typename remove_const<
  80. typename remove_volatile<T>::type>::type type;
  81. };
  82. //----------------------------------------------------------------------------
  83. template<class T> struct remove_reference { typedef T type; };
  84. template<class T> struct remove_reference<T &> { typedef T type; };
  85. #if __cpp_rvalue_references
  86. template<class T> struct remove_reference<T &&> { typedef T type; };
  87. #endif
  88. //----------------------------------------------------------------------------
  89. template<class T> struct remove_pointer { typedef T type; };
  90. template<class T> struct remove_pointer<T *> { typedef T type; };
  91. //----------------------------------------------------------------------------
  92. template<bool Cond, class Then, class Else>
  93. struct conditional { typedef Then type; };
  94. template<class Then, class Else>
  95. struct conditional<false, Then, Else> { typedef Else type; };
  96. //----------------------------------------------------------------------------
  97. template<bool Test, class T = void>
  98. struct enable_if
  99. {
  100. typedef T type;
  101. };
  102. template<class T>
  103. struct enable_if<false, T> {};
  104. //----------------------------------------------------------------------------
  105. #endif // __VIC_HAVE_TYPE_TRAITS
  106. //----------------------------------------------------------------------------
  107. template<class T> struct is_signed_integer : false_type {};
  108. template<> struct is_signed_integer<long> : true_type {};
  109. template<> struct is_signed_integer<int> : true_type {};
  110. template<> struct is_signed_integer<short> : true_type {};
  111. template<> struct is_signed_integer<signed char> : true_type {};
  112. template<class T> struct is_unsigned_integer : false_type {};
  113. template<> struct is_unsigned_integer<unsigned long> : true_type {};
  114. template<> struct is_unsigned_integer<unsigned int> : true_type {};
  115. template<> struct is_unsigned_integer<unsigned short> : true_type {};
  116. template<> struct is_unsigned_integer<unsigned char> : true_type {};
  117. #ifdef __VIC_LONGLONG
  118. template<> struct is_signed_integer<__VIC_LONGLONG> : true_type {};
  119. template<> struct is_unsigned_integer<unsigned __VIC_LONGLONG> : true_type {};
  120. #endif
  121. //----------------------------------------------------------------------------
  122. template<bool Test, class T = void>
  123. struct disable_if : enable_if<!Test, T> {};
  124. //----------------------------------------------------------------------------
  125. #if __cpp_lib_remove_cvref
  126. using std::remove_cvref;
  127. using std::remove_cvref_t;
  128. #else
  129. template<class T> struct remove_cvref
  130. {
  131. typedef typename remove_cv<
  132. typename remove_reference<T>::type>::type type;
  133. };
  134. #if __cpp_alias_templates
  135. template<class T> using remove_cvref_t = typename remove_cvref<T>::type;
  136. #endif
  137. #endif
  138. //----------------------------------------------------------------------------
  139. #if __cpp_alias_templates
  140. template<class T> using remove_const_t = typename remove_const<T>::type;
  141. template<class T> using remove_volatile_t = typename remove_volatile<T>::type;
  142. template<class T> using remove_cv_t = typename remove_cv<T>::type;
  143. template<class T> using remove_reference_t = typename remove_reference<T>::type;
  144. template<class T> using remove_pointer_t = typename remove_pointer<T>::type;
  145. template<bool Cond, class Then, class Else>
  146. using conditional_t = typename conditional<Cond, Then, Else>::type;
  147. // No alias for enable_if because in C++11 SFINAE is not guaranteed
  148. #endif
  149. //----------------------------------------------------------------------------
  150. #if !__cpp_lib_logical_traits
  151. template<class B> struct negation :
  152. integral_constant<bool, !bool(B::value)> {};
  153. #endif
  154. //----------------------------------------------------------------------------
  155. #if __cpp_lib_integer_sequence
  156. using std::index_sequence;
  157. using std::make_index_sequence;
  158. #elif __cpp_variadic_templates && __cpp_alias_templates
  159. //////////////////////////////////////////////////////////////////////////////
  160. template<size_t... I>
  161. struct index_sequence
  162. {
  163. static constexpr size_t size() { return sizeof...(I); }
  164. };
  165. //////////////////////////////////////////////////////////////////////////////
  166. // O(log N) implementation from here:
  167. // http://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence
  168. template<typename Seq1, typename Seq2>
  169. struct concat_sequence_;
  170. template<size_t... I1, size_t... I2>
  171. struct concat_sequence_<index_sequence<I1...>, index_sequence<I2...>>
  172. {
  173. using type = index_sequence<I1..., (sizeof...(I1) + I2)...>;
  174. };
  175. //////////////////////////////////////////////////////////////////////////////
  176. template<size_t Size>
  177. struct make_index_sequence_ : concat_sequence_<
  178. typename make_index_sequence_<Size/2>::type,
  179. typename make_index_sequence_<Size - Size/2>::type
  180. >{};
  181. template<> struct make_index_sequence_<0> { using type = index_sequence<>; };
  182. template<> struct make_index_sequence_<1> { using type = index_sequence<0>; };
  183. //////////////////////////////////////////////////////////////////////////////
  184. template<size_t Size>
  185. using make_index_sequence = typename make_index_sequence_<Size>::type;
  186. #endif
  187. //----------------------------------------------------------------------------
  188. } // namespace
  189. #endif // header guard