Horizon
meta_fwd.hpp
Go to the documentation of this file.
1 //
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 #define META_TYPE_CONSTRAINT(...) typename
152 #else
153 #define META_CONCEPT concept
154 #define META_CONCEPT_BARRIER(...) __VA_ARGS__
155 #define META_TYPE_CONSTRAINT(...) __VA_ARGS__
156 #endif
157 #else
158 #define META_TYPE_CONSTRAINT(...) typename
159 #endif
160 
161 #if (defined(__cpp_lib_type_trait_variable_templates) && \
162  __cpp_lib_type_trait_variable_templates > 0)
163 #define META_CXX_TRAIT_VARIABLE_TEMPLATES 1
164 #else
165 #define META_CXX_TRAIT_VARIABLE_TEMPLATES 0
166 #endif
167 
168 #if defined(__clang__)
169 #define META_IS_SAME(...) __is_same(__VA_ARGS__)
170 #elif defined(__GNUC__) && __GNUC__ >= 6
171 #define META_IS_SAME(...) __is_same_as(__VA_ARGS__)
172 #elif META_CXX_TRAIT_VARIABLE_TEMPLATES
173 #define META_IS_SAME(...) std::is_same_v<__VA_ARGS__>
174 #else
175 #define META_IS_SAME(...) std::is_same<__VA_ARGS__>::value
176 #endif
177 
178 #if defined(__GNUC__) || defined(_MSC_VER)
179 #define META_IS_BASE_OF(...) __is_base_of(__VA_ARGS__)
180 #elif META_CXX_TRAIT_VARIABLE_TEMPLATES
181 #define META_IS_BASE_OF(...) std::is_base_of_v<__VA_ARGS__>
182 #else
183 #define META_IS_BASE_OF(...) std::is_base_of<__VA_ARGS__>::value
184 #endif
185 
186 #if defined(__clang__) || defined(_MSC_VER) || \
187  (defined(__GNUC__) && __GNUC__ >= 8)
188 #define META_IS_CONSTRUCTIBLE(...) __is_constructible(__VA_ARGS__)
189 #elif META_CXX_TRAIT_VARIABLE_TEMPLATES
190 #define META_IS_CONSTRUCTIBLE(...) std::is_constructible_v<__VA_ARGS__>
191 #else
192 #define META_IS_CONSTRUCTIBLE(...) std::is_constructible<__VA_ARGS__>::value
193 #endif
194 
196 // Non-portable forward declarations of standard containers
197 #ifdef _LIBCPP_VERSION
198 #define META_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
199 #define META_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
200 #elif defined(_MSVC_STL_VERSION)
201 #define META_BEGIN_NAMESPACE_STD _STD_BEGIN
202 #define META_END_NAMESPACE_STD _STD_END
203 #else
204 #define META_BEGIN_NAMESPACE_STD namespace std {
205 #define META_END_NAMESPACE_STD }
206 #endif
207 
208 #if defined(__GLIBCXX__)
209 #define META_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
210 #define META_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
211 #define META_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
212 #define META_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER
213 #else
214 #define META_BEGIN_NAMESPACE_VERSION
215 #define META_END_NAMESPACE_VERSION
216 #define META_BEGIN_NAMESPACE_CONTAINER
217 #define META_END_NAMESPACE_CONTAINER
218 #endif
219 
220 #if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 4000
221 #define META_TEMPLATE_VIS _LIBCPP_TEMPLATE_VIS
222 #elif defined(_LIBCPP_VERSION)
223 #define META_TEMPLATE_VIS _LIBCPP_TYPE_VIS_ONLY
224 #else
225 #define META_TEMPLATE_VIS
226 #endif
228 
229 namespace meta
230 {
231 #if META_CXX_INTEGER_SEQUENCE
232  using std::integer_sequence;
233 #else
234  template <typename T, T...>
235  struct integer_sequence;
236 #endif
237 
238  template <typename... Ts>
239  struct list;
240 
241  template <typename T>
242  struct id;
243 
244  template <template <typename...> class>
245  struct quote;
246 
247  template <typename T, template <T...> class F>
248  struct quote_i;
249 
250  template <template <typename...> class C, typename... Ts>
251  struct defer;
252 
253  template <typename T, template <T...> class C, T... Is>
254  struct defer_i;
255 
256 #if META_CXX_VARIABLE_TEMPLATES || defined(META_DOXYGEN_INVOKED)
261  template <typename, template <typename...> class>
262  META_INLINE_VAR constexpr bool is_v = false;
263  template <typename... Ts, template <typename...> class C>
264  META_INLINE_VAR constexpr bool is_v<C<Ts...>, C> = true;
265 #endif
266 
267 #ifdef META_CONCEPT
268  namespace detail
269  {
270  template <bool B>
271  META_INLINE_VAR constexpr bool barrier = B;
272 
273  template <class T, T> struct require_constant; // not defined
274  }
275 
276  template <typename...>
277  META_CONCEPT is_true = META_CONCEPT_BARRIER(true);
278 
279  template <typename T, typename U>
280  META_CONCEPT same_as =
281  META_CONCEPT_BARRIER(META_IS_SAME(T, U));
282 
283  template <template <typename...> class C, typename... Ts>
284  META_CONCEPT valid = requires
285  {
286  typename C<Ts...>;
287  };
288 
289  template <typename T, template <T...> class C, T... Is>
290  META_CONCEPT valid_i = requires
291  {
292  typename C<Is...>;
293  };
294 
295  template <typename T>
296  META_CONCEPT trait = requires
297  {
298  typename T::type;
299  };
300 
301  template <typename T>
302  META_CONCEPT invocable = requires
303  {
304  typename quote<T::template invoke>;
305  };
306 
307  template <typename T>
308  META_CONCEPT list_like = is_v<T, list>;
309 
310  // clang-format off
311  template <typename T>
312  META_CONCEPT integral = requires
313  {
314  typename T::type;
315  typename T::value_type;
316  typename T::type::value_type;
317  }
318  && same_as<typename T::value_type, typename T::type::value_type>
319 #if META_CXX_TRAIT_VARIABLE_TEMPLATES
320  && std::is_integral_v<typename T::value_type>
321 #else
322  && std::is_integral<typename T::value_type>::value
323 #endif
324 
325  && requires
326  {
327  // { T::value } -> same_as<const typename T::value_type&>;
328  T::value;
329  requires same_as<decltype(T::value), const typename T::value_type>;
330  typename detail::require_constant<decltype(T::value), T::value>;
331 
332  // { T::type::value } -> same_as<const typename T::value_type&>;
333  T::type::value;
334  requires same_as<decltype(T::type::value), const typename T::value_type>;
335  typename detail::require_constant<decltype(T::type::value), T::type::value>;
336  requires T::value == T::type::value;
337 
338  // { T{}() } -> same_as<typename T::value_type>;
339  T{}();
340  requires same_as<decltype(T{}()), typename T::value_type>;
341  typename detail::require_constant<decltype(T{}()), T{}()>;
342  requires T{}() == T::value;
343 
344  // { T{} } -> typename T::value_type;
345  };
346  // clang-format on
347 #endif // META_CONCEPT
348 
349  namespace extension
350  {
351  template <META_TYPE_CONSTRAINT(invocable) F, typename L>
352  struct apply;
353  }
354 } // namespace meta
355 
356 #ifdef __clang__
357 #pragma GCC diagnostic pop
358 #endif
359 
360 #endif
CPP_concept same_as
\concept same_as
Definition: concepts.hpp:853
CPP_concept is_true
\concept is_true
Definition: concepts.hpp:833
CPP_concept integral
\concept integral
Definition: concepts.hpp:947
CPP_concept invocable
\concept invocable
Definition: concepts.hpp:48
_t< extension::apply< Fn, L > > apply
Applies the invocable Fn using the types in the type list L as arguments.
Definition: meta.hpp:1030
defer< id, T > id
Definition: meta.hpp:585
Tiny metaprogramming library.
Definition: meta.hpp:116