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