You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

360 lines
9.9KB

  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
  125. #if !META_CXX_VARIABLE_TEMPLATES
  126. #error Concepts, but no variable templates?
  127. #endif
  128. #if __cpp_concepts <= 201507L
  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. #else
  133. #define META_CONCEPT concept
  134. #define META_CONCEPT_BARRIER(...) __VA_ARGS__
  135. #endif
  136. #define META_TYPE_CONSTRAINT(...) __VA_ARGS__
  137. #else
  138. #define META_TYPE_CONSTRAINT(...) typename
  139. #endif
  140. #if (defined(__cpp_lib_type_trait_variable_templates) && \
  141. __cpp_lib_type_trait_variable_templates > 0)
  142. #define META_CXX_TRAIT_VARIABLE_TEMPLATES 1
  143. #else
  144. #define META_CXX_TRAIT_VARIABLE_TEMPLATES 0
  145. #endif
  146. #if defined(__clang__)
  147. #define META_IS_SAME(...) __is_same(__VA_ARGS__)
  148. #elif defined(__GNUC__) && __GNUC__ >= 6
  149. #define META_IS_SAME(...) __is_same_as(__VA_ARGS__)
  150. #elif META_CXX_TRAIT_VARIABLE_TEMPLATES
  151. #define META_IS_SAME(...) std::is_same_v<__VA_ARGS__>
  152. #else
  153. #define META_IS_SAME(...) std::is_same<__VA_ARGS__>::value
  154. #endif
  155. #if defined(__GNUC__) || defined(_MSC_VER)
  156. #define META_IS_BASE_OF(...) __is_base_of(__VA_ARGS__)
  157. #elif META_CXX_TRAIT_VARIABLE_TEMPLATES
  158. #define META_IS_BASE_OF(...) std::is_base_of_v<__VA_ARGS__>
  159. #else
  160. #define META_IS_BASE_OF(...) std::is_base_of<__VA_ARGS__>::value
  161. #endif
  162. #if defined(__clang__) || defined(_MSC_VER) || \
  163. (defined(__GNUC__) && __GNUC__ >= 8)
  164. #define META_IS_CONSTRUCTIBLE(...) __is_constructible(__VA_ARGS__)
  165. #elif META_CXX_TRAIT_VARIABLE_TEMPLATES
  166. #define META_IS_CONSTRUCTIBLE(...) std::is_constructible_v<__VA_ARGS__>
  167. #else
  168. #define META_IS_CONSTRUCTIBLE(...) std::is_constructible<__VA_ARGS__>::value
  169. #endif
  170. /// \cond
  171. // Non-portable forward declarations of standard containers
  172. #ifdef _LIBCPP_VERSION
  173. #define META_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
  174. #define META_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
  175. #elif defined(_MSVC_STL_VERSION)
  176. #define META_BEGIN_NAMESPACE_STD _STD_BEGIN
  177. #define META_END_NAMESPACE_STD _STD_END
  178. #else
  179. #define META_BEGIN_NAMESPACE_STD namespace std {
  180. #define META_END_NAMESPACE_STD }
  181. #endif
  182. #if defined(__GLIBCXX__)
  183. #define META_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
  184. #define META_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
  185. #define META_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
  186. #define META_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER
  187. #else
  188. #define META_BEGIN_NAMESPACE_VERSION
  189. #define META_END_NAMESPACE_VERSION
  190. #define META_BEGIN_NAMESPACE_CONTAINER
  191. #define META_END_NAMESPACE_CONTAINER
  192. #endif
  193. #if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 4000
  194. #define META_TEMPLATE_VIS _LIBCPP_TEMPLATE_VIS
  195. #elif defined(_LIBCPP_VERSION)
  196. #define META_TEMPLATE_VIS _LIBCPP_TYPE_VIS_ONLY
  197. #else
  198. #define META_TEMPLATE_VIS
  199. #endif
  200. /// \endcond
  201. namespace meta
  202. {
  203. #if META_CXX_INTEGER_SEQUENCE
  204. using std::integer_sequence;
  205. #else
  206. template <typename T, T...>
  207. struct integer_sequence;
  208. #endif
  209. template <typename... Ts>
  210. struct list;
  211. template <typename T>
  212. struct id;
  213. template <template <typename...> class>
  214. struct quote;
  215. template <typename T, template <T...> class F>
  216. struct quote_i;
  217. template <template <typename...> class C, typename... Ts>
  218. struct defer;
  219. template <typename T, template <T...> class C, T... Is>
  220. struct defer_i;
  221. #if META_CXX_VARIABLE_TEMPLATES || defined(META_DOXYGEN_INVOKED)
  222. /// is_v
  223. /// Test whether a type \p T is an instantiation of class
  224. /// template \p C.
  225. /// \ingroup trait
  226. template <typename, template <typename...> class>
  227. META_INLINE_VAR constexpr bool is_v = false;
  228. template <typename... Ts, template <typename...> class C>
  229. META_INLINE_VAR constexpr bool is_v<C<Ts...>, C> = true;
  230. #endif
  231. #ifdef META_CONCEPT
  232. namespace detail
  233. {
  234. template <bool B>
  235. META_INLINE_VAR constexpr bool barrier = B;
  236. template <class T, T> struct require_constant; // not defined
  237. }
  238. template <typename...>
  239. META_CONCEPT is_true = META_CONCEPT_BARRIER(true);
  240. template <typename T, typename U>
  241. META_CONCEPT same_as =
  242. META_CONCEPT_BARRIER(META_IS_SAME(T, U));
  243. template <template <typename...> class C, typename... Ts>
  244. META_CONCEPT valid = requires
  245. {
  246. typename C<Ts...>;
  247. };
  248. template <typename T, template <T...> class C, T... Is>
  249. META_CONCEPT valid_i = requires
  250. {
  251. typename C<Is...>;
  252. };
  253. template <typename T>
  254. META_CONCEPT trait = requires
  255. {
  256. typename T::type;
  257. };
  258. template <typename T>
  259. META_CONCEPT invocable = requires
  260. {
  261. typename quote<T::template invoke>;
  262. };
  263. template <typename T>
  264. META_CONCEPT list_like = is_v<T, list>;
  265. // clang-format off
  266. template <typename T>
  267. META_CONCEPT integral = requires
  268. {
  269. typename T::type;
  270. typename T::value_type;
  271. typename T::type::value_type;
  272. }
  273. && same_as<typename T::value_type, typename T::type::value_type>
  274. #if META_CXX_TRAIT_VARIABLE_TEMPLATES
  275. && std::is_integral_v<typename T::value_type>
  276. #else
  277. && std::is_integral<typename T::value_type>::value
  278. #endif
  279. && requires
  280. {
  281. // { T::value } -> same_as<const typename T::value_type&>;
  282. T::value;
  283. requires same_as<decltype(T::value), const typename T::value_type>;
  284. typename detail::require_constant<decltype(T::value), T::value>;
  285. // { T::type::value } -> same_as<const typename T::value_type&>;
  286. T::type::value;
  287. requires same_as<decltype(T::type::value), const typename T::value_type>;
  288. typename detail::require_constant<decltype(T::type::value), T::type::value>;
  289. requires T::value == T::type::value;
  290. // { T{}() } -> same_as<typename T::value_type>;
  291. T{}();
  292. requires same_as<decltype(T{}()), typename T::value_type>;
  293. typename detail::require_constant<decltype(T{}()), T{}()>;
  294. requires T{}() == T::value;
  295. { T{} } -> typename T::value_type;
  296. };
  297. // clang-format on
  298. #endif // META_CONCEPT
  299. namespace extension
  300. {
  301. template <META_TYPE_CONSTRAINT(invocable) F, typename L>
  302. struct apply;
  303. }
  304. } // namespace meta
  305. #ifdef __clang__
  306. #pragma GCC diagnostic pop
  307. #endif
  308. #endif