1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef _LIBCPP___TYPE_TRAITS_CONJUNCTION_H
10 #define _LIBCPP___TYPE_TRAITS_CONJUNCTION_H
11 
12 #include <__config>
13 #include <__type_traits/conditional.h>
14 #include <__type_traits/enable_if.h>
15 #include <__type_traits/integral_constant.h>
16 
17 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
18 #  pragma GCC system_header
19 #endif
20 
21 _LIBCPP_BEGIN_NAMESPACE_STD
22 
23 template <class...>
24 using __expand_to_true = true_type;
25 
26 template <class... _Pred>
27 __expand_to_true<__enable_if_t<_Pred::value>...> __and_helper(int);
28 
29 template <class...>
30 false_type __and_helper(...);
31 
32 // _And always performs lazy evaluation of its arguments.
33 //
34 // However, `_And<_Pred...>` itself will evaluate its result immediately (without having to
35 // be instantiated) since it is an alias, unlike `conjunction<_Pred...>`, which is a struct.
36 // If you want to defer the evaluation of `_And<_Pred...>` itself, use `_Lazy<_And, _Pred...>`.
37 template <class... _Pred>
38 using _And _LIBCPP_NODEBUG = decltype(std::__and_helper<_Pred...>(0));
39 
40 #if _LIBCPP_STD_VER > 14
41 
42 template <class...>
43 struct conjunction : true_type {};
44 
45 template <class _Arg>
46 struct conjunction<_Arg> : _Arg {};
47 
48 template <class _Arg, class... _Args>
49 struct conjunction<_Arg, _Args...> : conditional_t<!bool(_Arg::value), _Arg, conjunction<_Args...>> {};
50 
51 template <class... _Args>
52 inline constexpr bool conjunction_v = conjunction<_Args...>::value;
53 
54 #endif // _LIBCPP_STD_VER > 14
55 
56 _LIBCPP_END_NAMESPACE_STD
57 
58 #endif // _LIBCPP___TYPE_TRAITS_CONJUNCTION_H
59