MongoDB C++ Driver  mongocxx-3.9.0
All Classes Namespaces Functions Typedefs Enumerations Enumerator Friends Pages
type_traits.hpp
1 #pragma once
2 
3 #include <type_traits>
4 
5 #include <bsoncxx/config/prelude.hpp>
6 
7 namespace bsoncxx {
8 inline namespace v_noabi {
9 namespace detail {
10 
11 #define bsoncxx_ttparam \
12  template <class...> \
13  class
14 
16 template <typename T>
17 using type_t = typename T::type;
18 
20 template <typename T>
21 using value_type_t = typename T::value_type;
22 
23 template <bool B, typename T = void>
24 using enable_if_t = typename std::enable_if<B, T>::type;
25 
26 #pragma push_macro("DECL_ALIAS")
27 #define DECL_ALIAS(Name) \
28  template <typename T> \
29  using Name##_t = type_t<std::Name<T>>
30 DECL_ALIAS(decay);
31 DECL_ALIAS(make_signed);
32 DECL_ALIAS(make_unsigned);
33 DECL_ALIAS(remove_reference);
34 DECL_ALIAS(remove_const);
35 DECL_ALIAS(remove_volatile);
36 DECL_ALIAS(remove_cv);
37 DECL_ALIAS(add_const);
38 DECL_ALIAS(add_volatile);
39 DECL_ALIAS(add_lvalue_reference);
40 DECL_ALIAS(add_rvalue_reference);
41 #pragma pop_macro("DECL_ALIAS")
42 
43 template <typename... Ts>
44 using common_type_t = type_t<std::common_type<Ts...>>;
45 
49 template <typename T>
50 using remove_cvref_t = remove_cv_t<remove_reference_t<T>>;
51 
55 template <typename T>
56 using const_reference_t = add_lvalue_reference_t<const remove_cvref_t<T>>;
57 
63 template <typename... Ts>
64 using void_t = void;
65 
69 template <bool B>
70 using bool_constant = std::integral_constant<bool, B>;
71 
77 template <typename...>
78 struct mp_list;
79 
81 namespace impl_detection {
82 
83 // Implementation of detection idiom for is_detected: true case
84 template <
85  // A metafunction to try and apply
86  bsoncxx_ttparam Oper,
87  // The arguments to be given. These are deduced from the mp_list argument
88  typename... Args,
89  // Apply the arguments to the metafunction. If this yields a type, this function
90  // will be viable. If substitution fails, this function is discarded from the
91  // overload set.
92  typename SfinaeHere = Oper<Args...>>
93 std::true_type is_detected_f(mp_list<Args...>*);
94 
95 // Failure case for is_detected. Because this function takes an elipsis, this is
96 // less preferred than the above overload that accepts a pointer type directly.
97 template <bsoncxx_ttparam Oper, typename... Args>
98 std::false_type is_detected_f(...);
99 
100 // Provides the detected_or impl
101 template <bool IsDetected>
102 struct detection;
103 
104 // Non-detected case:
105 template <>
106 struct detection<false> {
107  // We just return the default, since the metafunction will not apply
108  template <typename Default, bsoncxx_ttparam, typename...>
109  using f = Default;
110 };
111 
112 // Detected case:
113 template <>
114 struct detection<true> {
115  template <typename, bsoncxx_ttparam Oper, typename... Args>
116  using f = Oper<Args...>;
117 };
118 
119 } // namespace impl_detection
120 
125 struct nonesuch {
126  ~nonesuch() = delete;
127  nonesuch(nonesuch const&) = delete;
128  void operator=(nonesuch const&) = delete;
129 };
130 
138 template <bsoncxx_ttparam Oper, typename... Args>
139 struct is_detected
140  : decltype(impl_detection::is_detected_f<Oper>(static_cast<mp_list<Args...>*>(nullptr))) {};
141 
150 template <typename Dflt, bsoncxx_ttparam Oper, typename... Args>
151 using detected_or = typename impl_detection::detection<
152  is_detected<Oper, Args...>::value>::template f<Dflt, Oper, Args...>;
153 
161 template <bsoncxx_ttparam Oper, typename... Args>
162 using detected_t = detected_or<nonesuch, Oper, Args...>;
163 
171 template <bool B>
172 struct conditional {
173  template <typename IfTrue, typename>
174  using f = IfTrue;
175 };
176 
177 template <>
178 struct conditional<false> {
179  template <typename, typename IfFalse>
180  using f = IfFalse;
181 };
182 
190 template <bool B, typename T, typename F>
191 using conditional_t = typename conditional<B>::template f<T, F>;
192 
193 // impl for conjunction+disjunction
194 namespace impl_logic {
195 
196 template <typename FalseType, typename Opers>
197 struct conj;
198 
199 template <typename H, typename... Tail>
200 struct conj<bool_constant<H::value || !sizeof...(Tail)>, mp_list<H, Tail...>> : H {};
201 
202 template <typename F, typename H, typename... Tail>
203 struct conj<F, mp_list<H, Tail...>> : conj<F, mp_list<Tail...>> {};
204 
205 template <typename H>
206 struct conj<std::false_type, mp_list<H>> : H {};
207 
208 template <>
209 struct conj<std::false_type, mp_list<>> : std::true_type {};
210 
211 template <typename TrueType, typename Opers>
212 struct disj;
213 
214 template <typename H, typename... Tail>
215 struct disj<bool_constant<H::value && sizeof...(Tail)>, mp_list<H, Tail...>> : H {};
216 
217 template <typename F, typename H, typename... Tail>
218 struct disj<F, mp_list<H, Tail...>> : disj<F, mp_list<Tail...>> {};
219 
220 template <typename H>
221 struct disj<std::true_type, mp_list<H>> : H {};
222 
223 template <>
224 struct disj<std::true_type, mp_list<>> : std::false_type {};
225 
226 } // namespace impl_logic
227 
236 template <typename... Cond>
237 struct conjunction : impl_logic::conj<std::false_type, mp_list<Cond...>> {};
238 
247 template <typename... Cond>
248 struct disjunction : impl_logic::disj<std::true_type, mp_list<Cond...>> {};
249 
255 template <typename T>
256 struct negation : bool_constant<!T::value> {};
257 
264 template <typename...>
265 using true_t = std::true_type;
266 
267 namespace impl_requires {
268 
269 template <typename R>
270 R norm_conjunction(...);
271 
272 template <typename R, typename... Cs>
273 conjunction<Cs...> norm_conjunction(const conjunction<Cs...>&);
274 
275 template <typename T>
276 using norm_conjunction_t = decltype(norm_conjunction<T>(std::declval<const T&>()));
277 
278 template <typename Constraint, typename = void>
279 struct requirement;
280 
281 template <typename FailingRequirement>
282 struct failed_requirement {
283  failed_requirement(int) = delete;
284 
285  template <typename T>
286  static T explain(failed_requirement);
287 };
288 
289 template <typename... SubRequirements>
290 struct failed_requirement<conjunction<SubRequirements...>> {
291  failed_requirement(int) = delete;
292 
293  template <typename T>
294  static auto explain(int)
295  -> common_type_t<decltype(requirement<SubRequirements>::test::template explain<T>(0))...>;
296 };
297 
298 template <typename Constraint, typename>
299 struct requirement {
300  using test = failed_requirement<impl_requires::norm_conjunction_t<Constraint>>;
301 };
302 
303 template <typename Constraint>
304 struct requirement<Constraint, enable_if_t<Constraint::value>> {
305  struct test {
306  template <typename T>
307  static T explain(int);
308  };
309 };
310 
311 } // namespace impl_requires
312 
322 template <typename Type, typename... Traits>
323 #if defined _MSC_VER && _MSC_VER < 1920
324 // VS 2015 has trouble with expression SFINAE.
325 using requires_t = enable_if_t<conjunction<Traits...>::value, Type>;
326 #else
327 // Generates better error messages in case of substitution failure than a plain enable_if_t:
328 using requires_t =
329  decltype(impl_requires::requirement<conjunction<Traits...>>::test::template explain<Type>(0));
330 #endif
331 
341 template <typename Type, typename... Traits>
342 using requires_not_t = requires_t<Type, negation<disjunction<Traits...>>>;
343 
344 // Impl: invoke/is_invocable
345 namespace impl_invoke {
346 
347 #pragma push_macro("RETURNS")
348 #define RETURNS(...) \
349  noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) { \
350  return __VA_ARGS__; \
351  } \
352  static_assert(true, "")
353 
354 template <bool IsMemberObject, bool IsMemberFunction>
355 struct invoker {
356  template <typename F, typename... Args>
357  constexpr static auto apply(F&& fun, Args&&... args)
358  RETURNS(static_cast<F&&>(fun)(static_cast<Args&&>(args)...));
359 };
360 
361 template <>
362 struct invoker<false, true> {
363  template <typename F, typename Self, typename... Args>
364  constexpr static auto apply(F&& fun, Self&& self, Args&&... args)
365  RETURNS((static_cast<Self&&>(self).*fun)(static_cast<Args&&>(args)...));
366 };
367 
368 template <>
369 struct invoker<true, false> {
370  template <typename F, typename Self>
371  constexpr static auto apply(F&& fun, Self&& self) RETURNS(static_cast<Self&&>(self).*fun);
372 };
373 
374 } // namespace impl_invoke
375 
376 static constexpr struct invoke_fn {
384  template <typename F, typename... Args, typename Fd = remove_cvref_t<F>>
385  constexpr auto operator()(F&& fn, Args&&... args) const
386  RETURNS(impl_invoke::invoker<std::is_member_object_pointer<Fd>::value,
387  std::is_member_function_pointer<Fd>::value> //
388  ::apply(static_cast<F&&>(fn), static_cast<Args&&>(args)...));
389 } invoke;
390 
391 #pragma pop_macro("RETURNS")
392 
399 template <typename F, typename... Args>
400 using invoke_result_t = decltype(invoke(std::declval<F>(), std::declval<Args>()...));
401 
408 template <typename Fun, typename... Args>
409 #if defined(_MSC_VER) && _MSC_VER < 1910
410 using is_invocable = is_detected<invoke_result_t, Fun, Args...>;
411 #else
412 struct is_invocable : is_detected<invoke_result_t, Fun, Args...> {
413 };
414 #endif
415 
420 template <typename T, typename U>
421 struct is_alike : std::is_same<remove_cvref_t<T>, remove_cvref_t<U>> {};
422 
423 } // namespace detail
424 
425 } // namespace v_noabi
426 
427 } // namespace bsoncxx
428 
429 #include <bsoncxx/config/postlude.hpp>
The top-level namespace for bsoncxx library entities.
Definition: element.hpp:24