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