[libcxx-commits] [libcxx] [libc++] Fix std::variant/std::invoke too eager instantiation (PR #151028)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Jul 31 01:42:10 PDT 2025
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/151028
>From 10260aa4b7bc7e49e35cc5f9f313f8140e46877b 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/variant | 22 +++++++++++++------
.../variant.variant/variant.ctor/T.pass.cpp | 16 ++++++++++++++
2 files changed, 31 insertions(+), 7 deletions(-)
diff --git a/libcxx/include/variant b/libcxx/include/variant
index 9beef146f203c..6f9f86929ef65 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -1182,13 +1182,21 @@ public:
_LIBCPP_HIDE_FROM_ABI constexpr variant(const variant&) = default;
_LIBCPP_HIDE_FROM_ABI constexpr variant(variant&&) = default;
- template < class _Arg,
- enable_if_t<!is_same_v<__remove_cvref_t<_Arg>, variant>, int> = 0,
- enable_if_t<!__is_inplace_type<__remove_cvref_t<_Arg>>::value, int> = 0,
- enable_if_t<!__is_inplace_index<__remove_cvref_t<_Arg>>::value, int> = 0,
- class _Tp = __variant_detail::__best_match_t<_Arg, _Types...>,
- size_t _Ip = __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
- enable_if_t<is_constructible_v<_Tp, _Arg>, int> = 0>
+ template <class _Arg,
+ bool = !is_same_v<__remove_cvref_t<_Arg>, variant> && !__is_inplace_type<__remove_cvref_t<_Arg>>::value &&
+ !__is_inplace_index<__remove_cvref_t<_Arg>>::value,
+ class = void>
+ struct __arg_overload_type {};
+
+ template <class _Arg>
+ struct __arg_overload_type<_Arg, true, __void_t<__variant_detail::__best_match_t<_Arg, _Types...>>> {
+ using type _LIBCPP_NODEBUG = __variant_detail::__best_match_t<_Arg, _Types...>;
+ };
+
+ template <class _Arg,
+ class _Tp = typename __arg_overload_type<_Arg>::type,
+ size_t _Ip = __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
+ enable_if_t<is_constructible_v<_Tp, _Arg>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr variant(_Arg&& __arg) noexcept(is_nothrow_constructible_v<_Tp, _Arg>)
: __impl_(in_place_index<_Ip>, std::forward<_Arg>(__arg)) {}
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..3c5cb3ca34971 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
+ 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