[gcc(refs/users/aoliva/heads/testme)] libstdc++: check value in std::{con, dis}junction
Alexandre Oliva
aoliva@gcc.gnu.org
Wed Apr 22 04:23:26 GMT 2026
https://gcc.gnu.org/g:da006eab854cb4cc8e9e672a038c107b71f141aa
commit da006eab854cb4cc8e9e672a038c107b71f141aa
Author: Alexandre Oliva <oliva@adacore.com>
Date: Thu Apr 16 01:06:14 2026 -0300
libstdc++: check value in std::{con,dis}junction
When std::{con,dis}junction is passed a type that doesn't have a
"value" static data member, or whose value doesn't convert to bool, is
ambiguous or inaccessible, we stop iterating over the types and use
that type for the {con,dis}junction, without any diagnostic.
We'd get a diagnostic when attempting to use its value data member as
a bool, but if the member isn't used, compilation is successful,
despite the failure to meet the requirements for "value" in
[meta.logical]/4.
Check that the selected type parameter's value member is convertible
to bool.
for libstdc++-v3/ChangeLog
* include/std/type_traits (disjunction, conjunction): Check
that value converts to bool.
Diff:
---
libstdc++-v3/include/std/type_traits | 15 ++++++++++--
.../logical_traits/requirements/junction_neg.cc | 27 ++++++++++++++++++++++
2 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 59be925e10a6..238450518c08 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -241,10 +241,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
} // namespace __detail
/// @endcond
+ template<typename _From, typename _To>
+ struct is_convertible;
+
template<typename... _Bn>
struct conjunction
: __detail::__conjunction_impl<void, _Bn...>::type
- { };
+ {
+ static_assert(is_convertible<decltype(__detail::__conjunction_impl<void, _Bn...>
+ ::type::value), bool>::value,
+ "result type's value is not convertible to bool");
+ };
template<>
struct conjunction<>
@@ -254,7 +261,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename... _Bn>
struct disjunction
: __detail::__disjunction_impl<void, _Bn...>::type
- { };
+ {
+ static_assert(is_convertible<decltype(__detail::__disjunction_impl<void, _Bn...>
+ ::type::value), bool>::value,
+ "result type's value is not convertible to bool");
+ };
template<>
struct disjunction<>
diff --git a/libstdc++-v3/testsuite/20_util/logical_traits/requirements/junction_neg.cc b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/junction_neg.cc
new file mode 100644
index 000000000000..eb0f246367f1
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/junction_neg.cc
@@ -0,0 +1,27 @@
+// { dg-do compile { target c++17 } }
+
+#include <type_traits>
+
+class S {}; // not convertible to bool
+
+struct T {
+ static constexpr S value{};
+};
+
+// 4 Every template type argument for which Bi::value is instantiated shall be
+// usable as a base class and shall have a member value which is convertible to
+// bool, is not hidden, and is unambiguously available in the type.
+
+std::conjunction<T> cT; // { dg-error "here" }
+std::conjunction<T, std::true_type> cTt; // { dg-error "here" }
+std::conjunction<T, std::false_type> cTf; // { dg-error "here" }
+std::conjunction<std::true_type, T> ctTtf; // { dg-error "here" }
+std::conjunction<std::false_type, T> cfTtf;
+
+std::disjunction<T> dT; // { dg-error "here" }
+std::disjunction<T, std::true_type> dTt; // { dg-error "here" }
+std::disjunction<T, std::false_type> dTf; // { dg-error "here" }
+std::disjunction<std::false_type, T> dfTtf; // { dg-error "here" }
+std::disjunction<std::true_type, T> dtTtf;
+
+// { dg-prune-output "not convertible to bool|evaluates to false" }
More information about the Libstdc++-cvs
mailing list