Phi
is_constructible.hpp
1 #ifndef INCG_PHI_CORE_TYPE_TRAITS_IS_CONSTRUCTIBLE_HPP
2 #define INCG_PHI_CORE_TYPE_TRAITS_IS_CONSTRUCTIBLE_HPP
3 
4 #include "phi/phi_config.hpp"
5 
6 #if PHI_HAS_EXTENSION_PRAGMA_ONCE()
7 # pragma once
8 #endif
9 
10 #include "phi/compiler_support/constexpr.hpp"
11 #include "phi/compiler_support/inline_variables.hpp"
12 #include "phi/compiler_support/intrinsics/is_constructible.hpp"
13 #include "phi/type_traits/integral_constant.hpp"
14 
15 #if PHI_SUPPORTS_IS_CONSTRUCTIBLE()
16 
17 # include "phi/compiler_support/warning.hpp"
18 
19 # define PHI_HAS_WORKING_IS_CONSTRUCTIBLE() 1
20 
21 DETAIL_PHI_BEGIN_NAMESPACE()
22 
23 PHI_GCC_SUPPRESS_WARNING_PUSH()
24 PHI_GCC_SUPPRESS_WARNING("-Wignored-qualifiers")
25 
26 template <typename TypeT, typename... ArgsT>
27 struct is_constructible : public integral_constant<bool, PHI_IS_CONSTRUCTIBLE(TypeT, ArgsT...)>
28 {};
29 
30 template <typename TypeT, typename... ArgsT>
31 struct is_not_constructible : public integral_constant<bool, !PHI_IS_CONSTRUCTIBLE(TypeT, ArgsT...)>
32 {};
33 
34 # if PHI_HAS_FEATURE_VARIABLE_TEMPLATE()
35 
36 template <typename TypeT, typename... ArgsT>
37 PHI_INLINE_VARIABLE PHI_CONSTEXPR bool is_constructible_v = PHI_IS_CONSTRUCTIBLE(TypeT, ArgsT...);
38 
39 template <typename TypeT, typename... ArgsT>
40 PHI_INLINE_VARIABLE PHI_CONSTEXPR bool is_not_constructible_v =
41  !PHI_IS_CONSTRUCTIBLE(TypeT, ArgsT...);
42 
43 # endif
44 
45 PHI_GCC_SUPPRESS_WARNING_POP()
46 
47 DETAIL_PHI_END_NAMESPACE()
48 
49 #else
50 
51 # include "phi/core/declval.hpp"
52 # include "phi/type_traits/conditional.hpp"
53 # include "phi/type_traits/is_base_of.hpp"
54 # include "phi/type_traits/is_default_constructible.hpp"
55 # include "phi/type_traits/is_destructible.hpp"
56 # include "phi/type_traits/is_lvalue_reference.hpp"
57 # include "phi/type_traits/is_reference.hpp"
58 # include "phi/type_traits/is_rvalue_reference.hpp"
59 # include "phi/type_traits/is_static_castable_to.hpp"
60 # include "phi/type_traits/is_void.hpp"
61 # include "phi/type_traits/remove_cv.hpp"
62 # include "phi/type_traits/remove_reference.hpp"
63 
64 # if PHI_HAS_WORKING_IS_DEFAULT_CONSTRUCTIBLE() && PHI_HAS_WORKING_IS_BASE_OF()
65 # define PHI_HAS_WORKING_IS_CONSTRUCTIBLE() 1
66 # else
67 # define PHI_HAS_WORKING_IS_CONSTRUCTIBLE() 0
68 # endif
69 
70 DETAIL_PHI_BEGIN_NAMESPACE()
71 
72 template <typename TypeT, typename... ArgsT>
74 
75 namespace detail
76 {
77  // Implementation for non-reference types. To meet the proper
78  // variable definition semantics, we also need to test for
79  // is_destructible in this case.
81  {
82  template <typename ToT, typename ArgT, typename = decltype(::new ToT(declval<ArgT>()))>
83  static true_type test(int);
84 
85  template <typename, typename>
86  static false_type test(...);
87  };
88 
89  template <typename ToT, typename ArgT>
91  {
92  using type = decltype(test<ToT, ArgT>(0));
93 
94  static PHI_CONSTEXPR_AND_CONST bool value = type::value;
95  };
96 
97  template <typename ToT, typename ArgT>
99  : public integral_constant<bool, is_destructible<ToT>::value &&
100  is_direct_constructible_impl<ToT, ArgT>::value>
101  {};
102 
103  template <typename FromT, typename ToT,
106 
107  // Detect whether we have a downcast situation during
108  // reference binding.
109  template <typename FromT, typename ToT>
111  {
113  using destination_t = typename remove_cv<typename remove_reference<ToT>::type>::type;
114 
115  using type =
119 
120  static PHI_CONSTEXPR_AND_CONST bool value = type::value;
121  };
122 
123  template <typename FromT, typename ToT>
124  struct is_base_to_derived_ref<FromT, ToT, false> : public false_type
125  {};
126 
127  template <typename FromT, typename ToT,
130 
131  // Detect whether we have an lvalue of non-function type
132  // bound to a reference-compatible rvalue-reference.
133  template <typename FromT, typename ToT>
134  struct is_lvalue_to_rvalue_ref<FromT, ToT, true>
135  {
137  using destination_t = typename remove_cv<typename remove_reference<ToT>::type>::type;
138 
142 
143  static PHI_CONSTEXPR_AND_CONST bool value = type::value;
144  };
145 
146  template <typename FromT, typename ToT>
147  struct is_lvalue_to_rvalue_ref<FromT, ToT, false> : public false_type
148  {};
149 
150  // Here we handle direct-initialization to a reference type as
151  // equivalent to a static_cast modulo overshooting conversions.
152  // These are restricted to the following conversions:
153  // a) A base class value to a derived class reference
154  // b) An lvalue to an rvalue-reference of reference-compatible
155  // types that are not functions
156  template <typename TypeT, typename ArgT>
158  : public integral_constant<bool, is_static_castable_to<ArgT, TypeT>::value &&
159  !(is_base_to_derived_ref<ArgT, TypeT>::value ||
160  is_lvalue_to_rvalue_ref<ArgT, TypeT>::value)>
161  {};
162 
163  template <typename TypeT, typename ArgT>
165  : public conditional<is_reference<TypeT>::value,
166  is_direct_constructible_ref_cast<TypeT, ArgT>,
167  is_direct_constructible_new_safe<TypeT, ArgT>>::type
168  {};
169 
170  template <typename TypeT, typename ArgT>
171  struct is_direct_constructible : public is_direct_constructible_new<TypeT, ArgT>::type
172  {};
173 
174  // Since default-construction and binary direct-initialization have
175  // been handled separately, the implementation of the remaining
176  // n-ary construction cases is rather straightforward. We can use
177  // here a functional cast, because array types are excluded anyway
178  // and this form is never interpreted as a C cast.
180  {
181  template <typename TypeT, typename... ArgsT,
182  typename = decltype(TypeT(declval<ArgsT>()...))>
183  static true_type test(int);
184 
185  template <typename, typename...>
186  static false_type test(...);
187  };
188 
189  template <typename TypeT, typename... ArgsT>
191  {
192  using type = decltype(test<TypeT, ArgsT...>(0));
193  };
194 
195  template <typename TypeT, typename... ArgsT>
196  struct is_nary_constructible : public is_nary_constructible_impl<TypeT, ArgsT...>::type
197  {
198  static_assert(sizeof...(ArgsT) > 1, "Only useful for > 1 arguments");
199  };
200 
201  template <typename TypeT, typename... ArgsT>
202  struct is_constructible_impl : public is_nary_constructible<TypeT, ArgsT...>
203  {};
204 
205  template <typename TypeT, typename ArgT>
206  struct is_constructible_impl<TypeT, ArgT> : public is_direct_constructible<TypeT, ArgT>
207  {};
208 
209  template <>
210  struct is_constructible_impl<void> : public false_type
211  {};
212 
213  template <>
214  struct is_constructible_impl<void const> : public false_type
215  {};
216 
217  template <>
218  struct is_constructible_impl<void volatile> : public false_type
219  {};
220 
221  template <>
222  struct is_constructible_impl<void const volatile> : public false_type
223  {};
224 
225  template <typename TypeT>
226  struct is_constructible_impl<TypeT> : public is_default_constructible<TypeT>
227  {};
228 } // namespace detail
229 
230 template <typename TypeT, typename... ArgsT>
231 struct is_constructible : public detail::is_constructible_impl<TypeT, ArgsT...>::type
232 {};
233 
234 template <typename TypeT, typename... ArgsT>
236  : public integral_constant<bool, !is_constructible<TypeT, ArgsT...>::value>
237 {};
238 
239 # if PHI_HAS_FEATURE_VARIABLE_TEMPLATE()
240 
241 template <typename TypeT, typename... ArgsT>
242 PHI_INLINE_VARIABLE PHI_CONSTEXPR bool is_constructible_v =
243  is_constructible<TypeT, ArgsT...>::value;
244 
245 template <typename TypeT, typename... ArgsT>
246 PHI_INLINE_VARIABLE PHI_CONSTEXPR bool is_not_constructible_v =
247  is_not_constructible<TypeT, ArgsT...>::value;
248 
249 # endif
250 
251 DETAIL_PHI_END_NAMESPACE()
252 
253 #endif
254 
255 #endif // INCG_PHI_CORE_TYPE_TRAITS_IS_CONSTRUCTIBLE_HPP
Definition: integral_constant.hpp:19
Definition: conditional.hpp:13
Definition: is_constructible.hpp:129
Definition: is_constructible.hpp:157
Definition: is_default_constructible.hpp:91
Definition: is_constructible.hpp:80
Definition: is_function.hpp:45
Definition: is_base_of.hpp:74
Definition: test_macros.hpp:18
Definition: is_constructible.hpp:235
Definition: remove_cv.hpp:28
Definition: is_constructible.hpp:105
Definition: is_rvalue_reference.hpp:40
Definition: is_constructible.hpp:110
Definition: swap.hpp:23
Definition: is_constructible.hpp:73
Definition: is_constructible.hpp:202
Definition: is_constructible.hpp:171
Definition: is_constructible.hpp:190
Definition: is_lvalue_reference.hpp:40
Definition: is_constructible.hpp:164
Definition: is_same.hpp:40
Definition: is_constructible.hpp:179
Definition: is_constructible.hpp:90
Definition: is_void.hpp:17
Definition: is_constructible.hpp:98
Definition: is_constructible.hpp:196