@@ -1289,10 +1289,26 @@ struct converter {
12891289 template <class T >
12901290 operator T () && noexcept (
12911291 std::is_nothrow_invocable_r_v<T, F, std::in_place_type_t <T>>)
1292- requires(std::is_invocable_r_v<T, F, std::in_place_type_t <T>>)
1292+ requires(std::is_invocable_r_v<T, F, std::in_place_type_t <T>> &&
1293+ !std::is_invocable_r_v<T, F, std::in_place_type_t <T&>> &&
1294+ !std::is_invocable_r_v<T, F, std::in_place_type_t <T &&>>)
12931295 {
12941296 return std::move (f_)(std::in_place_type<T>);
12951297 }
1298+ template <class T >
1299+ operator T&() && noexcept (
1300+ std::is_nothrow_invocable_r_v<T&, F, std::in_place_type_t <T&>>)
1301+ requires (std::is_invocable_r_v<T&, F, std::in_place_type_t <T&>>)
1302+ {
1303+ return std::move (f_)(std::in_place_type<T&>);
1304+ }
1305+ template <class T >
1306+ operator T&&() && noexcept (
1307+ std::is_nothrow_invocable_r_v<T&&, F, std::in_place_type_t <T&&>>)
1308+ requires (std::is_invocable_r_v<T &&, F, std::in_place_type_t <T &&>>)
1309+ {
1310+ return std::move (f_)(std::in_place_type<T&&>);
1311+ }
12961312
12971313private:
12981314 F f_;
@@ -2347,14 +2363,29 @@ struct sign {
23472363template <std::size_t N>
23482364sign (const char (&str)[N]) -> sign<N - 1u>;
23492365
2350- struct wildcard {
2351- wildcard () = delete ;
2366+ // When std::reference_constructs_from_temporary_v (C++23) is not available, we
2367+ // fall back to a conservative approximation that disallows binding a temporary
2368+ // to a reference type if the source type is not a reference or if the source
2369+ // and target reference types are not compatible.
2370+ template <class T , class U >
2371+ concept explicitly_convertible =
2372+ std::is_constructible_v<U, T> &&
2373+ #if __cpp_lib_reference_from_temporary >= 202202L
2374+ !std::reference_constructs_from_temporary_v<U, T>;
2375+ #else
2376+ (!std::is_reference_v<U> ||
2377+ (std::is_reference_v<T> &&
2378+ std::is_convertible_v<std::add_pointer_t <std::remove_reference_t <T>>,
2379+ std::add_pointer_t <std::remove_reference_t <U>>>));
2380+ #endif // __cpp_lib_reference_from_temporary >= 202202L
23522381
2382+ struct noreturn_conversion {
23532383 template <class T >
2354- [[noreturn]] operator T () const {
2384+ [[noreturn]] PRO4D_STATIC_CALL(T, std:: in_place_type_t <T>) {
23552385 PROD_UNREACHABLE ();
23562386 }
23572387};
2388+ using wildcard = converter<noreturn_conversion>;
23582389
23592390} // namespace details
23602391
@@ -2578,9 +2609,9 @@ struct explicit_conversion_dispatch : details::cast_dispatch_base<true, false> {
25782609 PRO4D_STATIC_CALL (auto , T&& self) noexcept {
25792610 return details::converter{
25802611 [&self]<class U >(std::in_place_type_t <U>) noexcept (
2581- std::is_nothrow_constructible_v<U, T>)
2582- requires (std::is_constructible_v<U, T >)
2583- { return U{ std::forward<T>(self)} ; }};
2612+ std::is_nothrow_constructible_v<U, T>) -> U
2613+ requires (details::explicitly_convertible < T &&, U >)
2614+ { return static_cast <U>( std::forward<T>(self)) ; }};
25842615 }
25852616};
25862617using conversion_dispatch = explicit_conversion_dispatch;
0 commit comments