meta_fwd.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /// \file meta_fwd.hpp Forward declarations
  2. //
  3. // Meta library
  4. //
  5. // Copyright Eric Niebler 2014-present
  6. //
  7. // Use, modification and distribution is subject to the
  8. // Boost Software License, Version 1.0. (See accompanying
  9. // file LICENSE_1_0.txt or copy at
  10. // http://www.boost.org/LICENSE_1_0.txt)
  11. //
  12. // Project home: https://github.com/ericniebler/meta
  13. //
  14. #ifndef META_FWD_HPP
  15. #define META_FWD_HPP
  16. #include <type_traits>
  17. #include <utility>
  18. #ifdef __clang__
  19. #pragma GCC diagnostic push
  20. #pragma GCC diagnostic ignored "-Wmissing-variable-declarations"
  21. #endif
  22. #define META_CXX_STD_14 201402L
  23. #define META_CXX_STD_17 201703L
  24. #if defined(_MSVC_LANG) && _MSVC_LANG > __cplusplus // Older clangs define _MSVC_LANG < __cplusplus
  25. #define META_CXX_VER _MSVC_LANG
  26. #else
  27. #define META_CXX_VER __cplusplus
  28. #endif
  29. #if defined(__apple_build_version__) || defined(__clang__)
  30. #if defined(__apple_build_version__) || (defined(__clang__) && __clang_major__ < 6)
  31. #define META_WORKAROUND_LLVM_28385 // https://llvm.org/bugs/show_bug.cgi?id=28385
  32. #endif
  33. #elif defined(_MSC_VER)
  34. #define META_HAS_MAKE_INTEGER_SEQ 1
  35. #if _MSC_VER < 1920
  36. #define META_WORKAROUND_MSVC_702792 // Bogus C4018 comparing constant expressions with dependent type
  37. #define META_WORKAROUND_MSVC_703656 // ICE with pack expansion inside decltype in alias template
  38. #endif
  39. #if _MSC_VER < 1921
  40. #define META_WORKAROUND_MSVC_756112 // fold expression + alias templates in template argument
  41. #endif
  42. #elif defined(__GNUC__)
  43. #define META_WORKAROUND_GCC_86356 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86356
  44. #if __GNUC__ < 8
  45. #define META_WORKAROUND_GCC_UNKNOWN1 // Older GCCs don't like fold + debug + -march=native
  46. #endif
  47. #if __GNUC__ == 5 && __GNUC_MINOR__ == 1
  48. #define META_WORKAROUND_GCC_66405 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66405
  49. #endif
  50. #if __GNUC__ < 5
  51. #define META_WORKAROUND_CWG_1558 // https://wg21.link/cwg1558
  52. #endif
  53. #endif
  54. #ifndef META_CXX_VARIABLE_TEMPLATES
  55. #ifdef __cpp_variable_templates
  56. #define META_CXX_VARIABLE_TEMPLATES __cpp_variable_templates
  57. #else
  58. #define META_CXX_VARIABLE_TEMPLATES (META_CXX_VER >= META_CXX_STD_14)
  59. #endif
  60. #endif
  61. #ifndef META_CXX_INLINE_VARIABLES
  62. #ifdef __cpp_inline_variables
  63. #define META_CXX_INLINE_VARIABLES __cpp_inline_variables
  64. #else
  65. #define META_CXX_INLINE_VARIABLES (META_CXX_VER >= META_CXX_STD_17)
  66. #endif
  67. #endif
  68. #ifndef META_INLINE_VAR
  69. #if META_CXX_INLINE_VARIABLES
  70. #define META_INLINE_VAR inline
  71. #else
  72. #define META_INLINE_VAR
  73. #endif
  74. #endif
  75. #ifndef META_CXX_INTEGER_SEQUENCE
  76. #ifdef __cpp_lib_integer_sequence
  77. #define META_CXX_INTEGER_SEQUENCE __cpp_lib_integer_sequence
  78. #else
  79. #define META_CXX_INTEGER_SEQUENCE (META_CXX_VER >= META_CXX_STD_14)
  80. #endif
  81. #endif
  82. #ifndef META_HAS_MAKE_INTEGER_SEQ
  83. #ifdef __has_builtin
  84. #if __has_builtin(__make_integer_seq)
  85. #define META_HAS_MAKE_INTEGER_SEQ 1
  86. #endif
  87. #endif
  88. #endif
  89. #ifndef META_HAS_MAKE_INTEGER_SEQ
  90. #define META_HAS_MAKE_INTEGER_SEQ 0
  91. #endif
  92. #ifndef META_HAS_TYPE_PACK_ELEMENT
  93. #ifdef __has_builtin
  94. #if __has_builtin(__type_pack_element)
  95. #define META_HAS_TYPE_PACK_ELEMENT 1
  96. #endif
  97. #endif
  98. #endif
  99. #ifndef META_HAS_TYPE_PACK_ELEMENT
  100. #define META_HAS_TYPE_PACK_ELEMENT 0
  101. #endif
  102. #if !defined(META_DEPRECATED) && !defined(META_DISABLE_DEPRECATED_WARNINGS)
  103. #if defined(__cpp_attribute_deprecated) || META_CXX_VER >= META_CXX_STD_14
  104. #define META_DEPRECATED(...) [[deprecated(__VA_ARGS__)]]
  105. #elif defined(__clang__) || defined(__GNUC__)
  106. #define META_DEPRECATED(...) __attribute__((deprecated(__VA_ARGS__)))
  107. #endif
  108. #endif
  109. #ifndef META_DEPRECATED
  110. #define META_DEPRECATED(...)
  111. #endif
  112. #ifndef META_CXX_FOLD_EXPRESSIONS
  113. #ifdef __cpp_fold_expressions
  114. #define META_CXX_FOLD_EXPRESSIONS __cpp_fold_expressions
  115. #else
  116. #define META_CXX_FOLD_EXPRESSIONS (META_CXX_VER >= META_CXX_STD_17)
  117. #endif
  118. #endif
  119. #if META_CXX_FOLD_EXPRESSIONS
  120. #if !META_CXX_VARIABLE_TEMPLATES
  121. #error Fold expressions, but no variable templates?
  122. #endif
  123. #endif
  124. #if (defined(__cpp_concepts) && __cpp_concepts > 0) || defined(META_DOXYGEN_INVOKED)
  125. #if !META_CXX_VARIABLE_TEMPLATES
  126. #error Concepts, but no variable templates?
  127. #endif
  128. #if __cpp_concepts <= 201507L && !defined(META_DOXYGEN_INVOKED)
  129. #define META_CONCEPT concept bool
  130. // TS concepts subsumption barrier for atomic expressions
  131. #define META_CONCEPT_BARRIER(...) ::meta::detail::barrier<__VA_ARGS__>
  132. #define META_TYPE_CONSTRAINT(...) typename
  133. #else
  134. #define META_CONCEPT concept
  135. #define META_CONCEPT_BARRIER(...) __VA_ARGS__
  136. #define META_TYPE_CONSTRAINT(...) __VA_ARGS__
  137. #endif
  138. #else
  139. #define META_TYPE_CONSTRAINT(...) typename
  140. #endif
  141. #if (defined(__cpp_lib_type_trait_variable_templates) && \
  142. __cpp_lib_type_trait_variable_templates > 0)
  143. #define META_CXX_TRAIT_VARIABLE_TEMPLATES 1
  144. #else
  145. #define META_CXX_TRAIT_VARIABLE_TEMPLATES 0
  146. #endif
  147. #if defined(__clang__)
  148. #define META_IS_SAME(...) __is_same(__VA_ARGS__)
  149. #elif defined(__GNUC__) && __GNUC__ >= 6
  150. #define META_IS_SAME(...) __is_same_as(__VA_ARGS__)
  151. #elif META_CXX_TRAIT_VARIABLE_TEMPLATES
  152. #define META_IS_SAME(...) std::is_same_v<__VA_ARGS__>
  153. #else
  154. #define META_IS_SAME(...) std::is_same<__VA_ARGS__>::value
  155. #endif
  156. #if defined(__GNUC__) || defined(_MSC_VER)
  157. #define META_IS_BASE_OF(...) __is_base_of(__VA_ARGS__)
  158. #elif META_CXX_TRAIT_VARIABLE_TEMPLATES
  159. #define META_IS_BASE_OF(...) std::is_base_of_v<__VA_ARGS__>
  160. #else
  161. #define META_IS_BASE_OF(...) std::is_base_of<__VA_ARGS__>::value
  162. #endif
  163. #if defined(__clang__) || defined(_MSC_VER) || \
  164. (defined(__GNUC__) && __GNUC__ >= 8)
  165. #define META_IS_CONSTRUCTIBLE(...) __is_constructible(__VA_ARGS__)
  166. #elif META_CXX_TRAIT_VARIABLE_TEMPLATES
  167. #define META_IS_CONSTRUCTIBLE(...) std::is_constructible_v<__VA_ARGS__>
  168. #else
  169. #define META_IS_CONSTRUCTIBLE(...) std::is_constructible<__VA_ARGS__>::value
  170. #endif
  171. /// \cond
  172. // Non-portable forward declarations of standard containers
  173. #ifdef _LIBCPP_VERSION
  174. #define META_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
  175. #define META_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
  176. #elif defined(_MSVC_STL_VERSION)
  177. #define META_BEGIN_NAMESPACE_STD _STD_BEGIN
  178. #define META_END_NAMESPACE_STD _STD_END
  179. #else
  180. #define META_BEGIN_NAMESPACE_STD namespace std {
  181. #define META_END_NAMESPACE_STD }
  182. #endif
  183. #if defined(__GLIBCXX__)
  184. #define META_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
  185. #define META_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
  186. #define META_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
  187. #define META_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER
  188. #else
  189. #define META_BEGIN_NAMESPACE_VERSION
  190. #define META_END_NAMESPACE_VERSION
  191. #define META_BEGIN_NAMESPACE_CONTAINER
  192. #define META_END_NAMESPACE_CONTAINER
  193. #endif
  194. #if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 4000
  195. #define META_TEMPLATE_VIS _LIBCPP_TEMPLATE_VIS
  196. #elif defined(_LIBCPP_VERSION)
  197. #define META_TEMPLATE_VIS _LIBCPP_TYPE_VIS_ONLY
  198. #else
  199. #define META_TEMPLATE_VIS
  200. #endif
  201. /// \endcond
  202. namespace meta
  203. {
  204. #if META_CXX_INTEGER_SEQUENCE
  205. using std::integer_sequence;
  206. #else
  207. template <typename T, T...>
  208. struct integer_sequence;
  209. #endif
  210. template <typename... Ts>
  211. struct list;
  212. template <typename T>
  213. struct id;
  214. template <template <typename...> class>
  215. struct quote;
  216. template <typename T, template <T...> class F>
  217. struct quote_i;
  218. template <template <typename...> class C, typename... Ts>
  219. struct defer;
  220. template <typename T, template <T...> class C, T... Is>
  221. struct defer_i;
  222. #if META_CXX_VARIABLE_TEMPLATES || defined(META_DOXYGEN_INVOKED)
  223. /// is_v
  224. /// Test whether a type \p T is an instantiation of class
  225. /// template \p C.
  226. /// \ingroup trait
  227. template <typename, template <typename...> class>
  228. META_INLINE_VAR constexpr bool is_v = false;
  229. template <typename... Ts, template <typename...> class C>
  230. META_INLINE_VAR constexpr bool is_v<C<Ts...>, C> = true;
  231. #endif
  232. #ifdef META_CONCEPT
  233. namespace detail
  234. {
  235. template <bool B>
  236. META_INLINE_VAR constexpr bool barrier = B;
  237. template <class T, T> struct require_constant; // not defined
  238. }
  239. template <typename...>
  240. META_CONCEPT is_true = META_CONCEPT_BARRIER(true);
  241. template <typename T, typename U>
  242. META_CONCEPT same_as =
  243. META_CONCEPT_BARRIER(META_IS_SAME(T, U));
  244. template <template <typename...> class C, typename... Ts>
  245. META_CONCEPT valid = requires
  246. {
  247. typename C<Ts...>;
  248. };
  249. template <typename T, template <T...> class C, T... Is>
  250. META_CONCEPT valid_i = requires
  251. {
  252. typename C<Is...>;
  253. };
  254. template <typename T>
  255. META_CONCEPT trait = requires
  256. {
  257. typename T::type;
  258. };
  259. template <typename T>
  260. META_CONCEPT invocable = requires
  261. {
  262. typename quote<T::template invoke>;
  263. };
  264. template <typename T>
  265. META_CONCEPT list_like = is_v<T, list>;
  266. // clang-format off
  267. template <typename T>
  268. META_CONCEPT integral = requires
  269. {
  270. typename T::type;
  271. typename T::value_type;
  272. typename T::type::value_type;
  273. }
  274. && same_as<typename T::value_type, typename T::type::value_type>
  275. #if META_CXX_TRAIT_VARIABLE_TEMPLATES
  276. && std::is_integral_v<typename T::value_type>
  277. #else
  278. && std::is_integral<typename T::value_type>::value
  279. #endif
  280. && requires
  281. {
  282. // { T::value } -> same_as<const typename T::value_type&>;
  283. T::value;
  284. requires same_as<decltype(T::value), const typename T::value_type>;
  285. typename detail::require_constant<decltype(T::value), T::value>;
  286. // { T::type::value } -> same_as<const typename T::value_type&>;
  287. T::type::value;
  288. requires same_as<decltype(T::type::value), const typename T::value_type>;
  289. typename detail::require_constant<decltype(T::type::value), T::type::value>;
  290. requires T::value == T::type::value;
  291. // { T{}() } -> same_as<typename T::value_type>;
  292. T{}();
  293. requires same_as<decltype(T{}()), typename T::value_type>;
  294. typename detail::require_constant<decltype(T{}()), T{}()>;
  295. requires T{}() == T::value;
  296. // { T{} } -> typename T::value_type;
  297. };
  298. // clang-format on
  299. #endif // META_CONCEPT
  300. namespace extension
  301. {
  302. template <META_TYPE_CONSTRAINT(invocable) F, typename L>
  303. struct apply;
  304. }
  305. } // namespace meta
  306. #ifdef __clang__
  307. #pragma GCC diagnostic pop
  308. #endif
  309. #endif