[libcxx-commits] [PATCH] D136318: [libc++] type_traits: fix short-circuiting in std::conjunction.

Aaron Jacobs via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Wed Oct 19 23:43:26 PDT 2022


jacobsa created this revision.
Herald added a project: All.
jacobsa requested review of this revision.
Herald added a project: libc++.
Herald added a subscriber: libcxx-commits.
Herald added a reviewer: libc++.

Replace the two-level implementation with a simpler one that directly
subclasses the predicates, avoiding the instantiation of the template to
get the `type` member in a situation where we should short-circuit. This
prevents incorrect diagnostics when the instantiated predicate contains
a static assertion.

Fixes #58490.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D136318

Files:
  libcxx/include/__type_traits/conjunction.h
  libcxx/test/std/utilities/meta/meta.logical/conjunction.compile.pass.cpp


Index: libcxx/test/std/utilities/meta/meta.logical/conjunction.compile.pass.cpp
===================================================================
--- libcxx/test/std/utilities/meta/meta.logical/conjunction.compile.pass.cpp
+++ libcxx/test/std/utilities/meta/meta.logical/conjunction.compile.pass.cpp
@@ -28,6 +28,11 @@
 struct ExplicitlyConvertibleToBool { explicit constexpr operator bool() const { return true; } };
 struct ValueExplicitlyConvertible { static constexpr ExplicitlyConvertibleToBool value {}; };
 
+template <int kVal>
+struct CannotBeTwo {
+  static_assert(kVal != 2);
+};
+
 static_assert( std::conjunction<>::value);
 static_assert( std::conjunction<std::true_type >::value);
 static_assert(!std::conjunction<std::false_type>::value);
@@ -85,3 +90,12 @@
 
 static_assert(std::is_base_of_v<ValueExplicitlyConvertible, std::conjunction<ValueExplicitlyConvertible>>);
 static_assert(std::conjunction_v<ValueExplicitlyConvertible, std::true_type>);
+
+// Regression test for issue 58490 (short-circuiting with static assertions).
+static_assert(!std::conjunction<std::false_type, CannotBeTwo<2>>::value);
+static_assert(!std::conjunction<std::false_type, CannotBeTwo<2>, std::false_type>::value);
+static_assert(!std::conjunction<std::false_type, CannotBeTwo<2>, std::true_type>::value);
+
+static_assert(!std::conjunction_v<std::false_type, CannotBeTwo<2>>);
+static_assert(!std::conjunction_v<std::false_type, CannotBeTwo<2>, std::false_type>);
+static_assert(!std::conjunction_v<std::false_type, CannotBeTwo<2>, std::true_type>);
Index: libcxx/include/__type_traits/conjunction.h
===================================================================
--- libcxx/include/__type_traits/conjunction.h
+++ libcxx/include/__type_traits/conjunction.h
@@ -20,26 +20,6 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-#if _LIBCPP_STD_VER > 14
-
-template <class _Arg, class... _Args>
-struct __conjunction_impl {
-  using type = conditional_t<!bool(_Arg::value), _Arg, typename __conjunction_impl<_Args...>::type>;
-};
-
-template <class _Arg>
-struct __conjunction_impl<_Arg> {
-  using type = _Arg;
-};
-
-template <class... _Args>
-struct conjunction : __conjunction_impl<true_type, _Args...>::type {};
-
-template<class... _Args>
-inline constexpr bool conjunction_v = conjunction<_Args...>::value;
-
-#endif // _LIBCPP_STD_VER > 14
-
 template <class...>
 using __expand_to_true = true_type;
 
@@ -52,6 +32,22 @@
 template <class... _Pred>
 using _And _LIBCPP_NODEBUG = decltype(__and_helper<_Pred...>(0));
 
+#if _LIBCPP_STD_VER > 14
+
+template <class...>
+struct conjunction : true_type {};
+
+template <class _Arg>
+struct conjunction<_Arg> : _Arg {};
+
+template <class _Arg, class... _Args>
+struct conjunction<_Arg, _Args...> : conditional_t<!bool(_Arg::value), _Arg, conjunction<_Args...>> {};
+
+template <class... _Args>
+inline constexpr bool conjunction_v = conjunction<_Args...>::value;
+
+#endif // _LIBCPP_STD_VER > 14
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP___TYPE_TRAITS_CONJUNCTION_H


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D136318.469123.patch
Type: text/x-patch
Size: 3015 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20221020/1fef1d42/attachment-0001.bin>


More information about the libcxx-commits mailing list