1010#define _LIBCPP___TYPE_TRAITS_CONJUNCTION_H
1111
1212#include < __config>
13+ #include < __type_traits/conditional.h>
14+ #include < __type_traits/enable_if.h>
1315#include < __type_traits/integral_constant.h>
1416#include < __type_traits/is_same.h>
1517
1921
2022_LIBCPP_BEGIN_NAMESPACE_STD
2123
22- template <bool >
23- struct _AndImpl ;
24+ template <class ... >
25+ using __expand_to_true _LIBCPP_NODEBUG = true_type ;
2426
25- template <>
26- struct _AndImpl <true > {
27- template <class _Res , class _First , class ... _Rest>
28- using _Result _LIBCPP_NODEBUG =
29- typename _AndImpl<bool (_First::value) && sizeof ...(_Rest) != 0 >::template _Result<_First, _Rest...>;
30- };
27+ template <class ... _Pred>
28+ __expand_to_true<__enable_if_t <_Pred::value>...> __and_helper (int );
3129
32- template <>
33- struct _AndImpl <false > {
34- template <class _Res , class ...>
35- using _Result _LIBCPP_NODEBUG = _Res;
36- };
30+ template <class ...>
31+ false_type __and_helper (...);
3732
3833// _And always performs lazy evaluation of its arguments.
3934//
4035// However, `_And<_Pred...>` itself will evaluate its result immediately (without having to
4136// be instantiated) since it is an alias, unlike `conjunction<_Pred...>`, which is a struct.
4237// If you want to defer the evaluation of `_And<_Pred...>` itself, use `_Lazy<_And, _Pred...>`.
43- template <class ... _Args >
44- using _And _LIBCPP_NODEBUG = typename _AndImpl< sizeof ...(_Args) != 0 >:: template _Result<true_type, _Args ...>;
38+ template <class ... _Pred >
39+ using _And _LIBCPP_NODEBUG = decltype (std::__and_helper<_Pred ...>( 0 )) ;
4540
4641template <bool ... _Preds>
4742struct __all_dummy ;
@@ -51,11 +46,22 @@ struct __all : _IsSame<__all_dummy<_Pred...>, __all_dummy<((void)_Pred, true)...
5146
5247#if _LIBCPP_STD_VER >= 17
5348
54- template <class ... _Args>
55- struct _LIBCPP_NO_SPECIALIZATIONS conjunction : _And<_Args...> {};
49+ template <class ...>
50+ struct _LIBCPP_NO_SPECIALIZATIONS conjunction : true_type {};
51+
52+ _LIBCPP_DIAGNOSTIC_PUSH
53+ # if __has_warning("-Winvalid-specialization")
54+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED (" -Winvalid-specialization" )
55+ # endif
56+ template <class _Arg >
57+ struct conjunction <_Arg> : _Arg {};
58+
59+ template <class _Arg , class ... _Args>
60+ struct conjunction <_Arg, _Args...> : conditional_t <!bool (_Arg::value), _Arg, conjunction<_Args...>> {};
61+ _LIBCPP_DIAGNOSTIC_POP
5662
5763template <class ... _Args>
58- _LIBCPP_NO_SPECIALIZATIONS inline constexpr bool conjunction_v = _And <_Args...>::value;
64+ _LIBCPP_NO_SPECIALIZATIONS inline constexpr bool conjunction_v = conjunction <_Args...>::value;
5965
6066#endif // _LIBCPP_STD_VER >= 17
6167
0 commit comments