[libcxx-commits] [libcxx] [libc++] Fix std::variant evaluating template arguments too eagerly (PR #151028)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Aug 5 01:08:49 PDT 2025
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/151028
>From d249e2babcb3b9641b07f245429f035f3fbde743 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 28 Jul 2025 21:35:47 +0200
Subject: [PATCH] [libc++] Fix std::variant/std::invoke too eager instantiation
---
libcxx/include/__type_traits/invoke.h | 10 +++++-----
.../variant.variant/variant.ctor/T.pass.cpp | 16 ++++++++++++++++
2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/libcxx/include/__type_traits/invoke.h b/libcxx/include/__type_traits/invoke.h
index 5ff2efbe5faaf..3f5626c014432 100644
--- a/libcxx/include/__type_traits/invoke.h
+++ b/libcxx/include/__type_traits/invoke.h
@@ -67,20 +67,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if __has_builtin(__builtin_invoke)
-template <class... _Args>
-using __invoke_result_t _LIBCPP_NODEBUG = decltype(__builtin_invoke(std::declval<_Args>()...));
-
template <class, class... _Args>
struct __invoke_result_impl {};
template <class... _Args>
-struct __invoke_result_impl<__void_t<__invoke_result_t<_Args...> >, _Args...> {
- using type _LIBCPP_NODEBUG = __invoke_result_t<_Args...>;
+struct __invoke_result_impl<__void_t<decltype(__builtin_invoke(std::declval<_Args>()...))>, _Args...> {
+ using type _LIBCPP_NODEBUG = decltype(__builtin_invoke(std::declval<_Args>()...));
};
template <class... _Args>
using __invoke_result _LIBCPP_NODEBUG = __invoke_result_impl<void, _Args...>;
+template <class... _Args>
+using __invoke_result_t _LIBCPP_NODEBUG = typename __invoke_result<_Args...>::type;
+
template <class... _Args>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __invoke_result_t<_Args...> __invoke(_Args&&... __args)
_NOEXCEPT_(noexcept(__builtin_invoke(std::forward<_Args>(__args)...))) {
diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp
index 142da1d820d9a..6111138726dbc 100644
--- a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp
@@ -173,6 +173,11 @@ void test_vector_bool() {
assert(std::get<0>(v) == true);
}
+struct ConvertibleFromAny {
+ template <class V>
+ ConvertibleFromAny(V) {}
+};
+
int main(int, char**) {
test_T_ctor_basic();
test_T_ctor_noexcept();
@@ -180,5 +185,16 @@ int main(int, char**) {
test_no_narrowing_check_for_class_types();
test_construction_with_repeated_types();
test_vector_bool();
+
+ { // Check that the constraints are evaluated lazily (see https://github.com/llvm/llvm-project/issues/151328)
+ struct Matcher {
+ Matcher() {}
+ Matcher(std::variant<ConvertibleFromAny>) {}
+ };
+
+ Matcher vec;
+ [[maybe_unused]] Matcher m = std::move(vec);
+ }
+
return 0;
}
More information about the libcxx-commits
mailing list