diff --git a/stl/inc/memory b/stl/inc/memory index 0a5e8e3833f..531faba69f6 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -3475,6 +3475,11 @@ public: } _NODISCARD _CONSTEXPR23 add_lvalue_reference_t<_Ty> operator*() const noexcept(noexcept(*_STD declval())) { +#ifdef __cpp_lib_reference_from_temporary + static_assert( + !reference_converts_from_temporary_v, decltype(*_STD declval())>, + "Can't return a temporary object from unique_ptr::operator*(). (N5014 [unique.ptr.single.observers]/1)"); +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ return *_Mypair._Myval2; } diff --git a/stl/inc/tuple b/stl/inc/tuple index cbb51e5ce56..f46ad59a7d9 100644 --- a/stl/inc/tuple +++ b/stl/inc/tuple @@ -204,6 +204,22 @@ using _Three_way_comparison_result_with_tuple_like_t = template concept _Tuple_like_non_tuple = !_Is_specialization_v<_Ty, tuple> && _Tuple_like<_Ty>; + +#ifdef __cpp_lib_reference_from_temporary +template +constexpr bool _Tuple_reference_constructs_from_temporary = false; +template +constexpr bool _Tuple_reference_constructs_from_temporary, _Args...> = + (reference_constructs_from_temporary_v<_TupleTypes, _Args> || ...); + +template >> +constexpr bool _Tuple_reference_constructs_from_temporary_for_tuple_like = false; +template + requires (tuple_size_v<_Tuple> == tuple_size_v>) +constexpr bool + _Tuple_reference_constructs_from_temporary_for_tuple_like<_Tuple, _TupleLike, index_sequence<_Indices...>> = + _Tuple_reference_constructs_from_temporary<_Tuple, decltype(_STD get<_Indices>(_STD declval<_TupleLike>()))...>; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template <> @@ -347,6 +363,14 @@ public: tuple(_This2&& _This_arg, _Rest2&&... _Rest_arg) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Exact_args_t{}, _STD forward<_This2>(_This_arg), _STD forward<_Rest2>(_Rest_arg)...) {} +#ifdef __cpp_lib_reference_from_temporary + template , + _STD _Tuple_constructible_val>, + int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) tuple(_This2&&, _Rest2&&...) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ tuple(const tuple&) = default; tuple(tuple&&) = default; @@ -358,6 +382,13 @@ public: constexpr explicit(_Tuple_conditional_explicit_v) tuple(tuple<_Other...>& _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _Right) {} +#ifdef __cpp_lib_reference_from_temporary + template , + _STD _Tuple_convert_val&, _Other...>>, + int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) tuple(tuple<_Other...>&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template , @@ -366,6 +397,13 @@ public: constexpr explicit(_Tuple_conditional_explicit_v) tuple(const tuple<_Other...>& _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _Right) {} +#ifdef __cpp_lib_reference_from_temporary + template , + _STD _Tuple_convert_val&, _Other...>>, + int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) tuple(const tuple<_Other...>&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ template , _STD _Tuple_convert_val, _Other...>>, @@ -373,6 +411,13 @@ public: constexpr explicit(_Tuple_conditional_explicit_v) tuple(tuple<_Other...>&& _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _STD move(_Right)) {} +#ifdef __cpp_lib_reference_from_temporary + template , + _STD _Tuple_convert_val, _Other...>>, + int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) tuple(tuple<_Other...>&&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #if _HAS_CXX23 template , @@ -381,11 +426,23 @@ public: constexpr explicit(_Tuple_conditional_explicit_v) tuple(const tuple<_Other...>&& _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _STD move(_Right)) {} +#ifdef __cpp_lib_reference_from_temporary + template , + _STD _Tuple_convert_val, _Other...>>, + int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) tuple(const tuple<_Other...>&&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ template , int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(pair<_First, _Second>& _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _Right) {} +#ifdef __cpp_lib_reference_from_temporary + template , int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) tuple(pair<_First, _Second>&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template & _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _Right) {} +#ifdef __cpp_lib_reference_from_temporary + template , int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) + tuple(const pair<_First, _Second>&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ template , int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(pair<_First, _Second>&& _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _STD move(_Right)) {} +#ifdef __cpp_lib_reference_from_temporary + template , int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) tuple(pair<_First, _Second>&&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #if _HAS_CXX23 template && _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _STD move(_Right)) {} +#ifdef __cpp_lib_reference_from_temporary + template , int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) + tuple(const pair<_First, _Second>&&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ template > static constexpr bool _Is_tuple_like_constructor_explicit_v = false; @@ -427,6 +503,15 @@ public: constexpr explicit(_Is_tuple_like_constructor_explicit_v<_Other>) tuple(_Other&& _Right) : tuple(_Unpack_tuple_t{}, _STD forward<_Other>(_Right)) { } +#ifdef __cpp_lib_reference_from_temporary + template <_Different_from _Other> + requires _Tuple_like_non_subrange<_Other> && (1 + sizeof...(_Rest) == tuple_size_v>) + && _Can_construct_values_from_tuple_like_v + && (sizeof...(_Rest) != 0 + || (!is_convertible_v<_Other, _This> && !is_constructible_v<_This, _Other>) ) + && _Tuple_reference_constructs_from_temporary_for_tuple_like + explicit(_Is_tuple_like_constructor_explicit_v<_Other>) tuple(_Other&&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template ) tuple(allocator_arg_t, const _Alloc& _Al, _This2&& _This_arg, _Rest2&&... _Rest_arg) : tuple(_Alloc_exact_args_t{}, _Al, _STD forward<_This2>(_This_arg), _STD forward<_Rest2>(_Rest_arg)...) {} +#ifdef __cpp_lib_reference_from_temporary + template , + _STD _Tuple_constructible_val>, + int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) + tuple(allocator_arg_t, const _Alloc&, _This2&&, _Rest2&&...) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ template , int> = 0> @@ -468,6 +562,15 @@ public: constexpr explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, tuple<_Other...>& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {} +#ifdef __cpp_lib_reference_from_temporary + template , + _STD _Tuple_convert_val&, _Other...>>, + int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) + tuple(allocator_arg_t, const _Alloc&, tuple<_Other...>&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template ) tuple(allocator_arg_t, const _Alloc& _Al, const tuple<_Other...>& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {} +#ifdef __cpp_lib_reference_from_temporary + template , + _STD _Tuple_convert_val&, _Other...>>, + int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) + tuple(allocator_arg_t, const _Alloc&, const tuple<_Other...>&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ template , @@ -485,6 +597,15 @@ public: _CONSTEXPR20 explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, tuple<_Other...>&& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} +#ifdef __cpp_lib_reference_from_temporary + template , + _STD _Tuple_convert_val, _Other...>>, + int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) + tuple(allocator_arg_t, const _Alloc&, tuple<_Other...>&&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #if _HAS_CXX23 template ) tuple(allocator_arg_t, const _Alloc& _Al, const tuple<_Other...>&& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} +#ifdef __cpp_lib_reference_from_temporary + template , + _STD _Tuple_convert_val, _Other...>>, + int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) + tuple(allocator_arg_t, const _Alloc&, const tuple<_Other...>&&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ template , int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, pair<_First, _Second>& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {} +#ifdef __cpp_lib_reference_from_temporary + template , int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) + tuple(allocator_arg_t, const _Alloc&, pair<_First, _Second>&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template ) tuple(allocator_arg_t, const _Alloc& _Al, const pair<_First, _Second>& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {} +#ifdef __cpp_lib_reference_from_temporary + template , int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) + tuple(allocator_arg_t, const _Alloc&, const pair<_First, _Second>&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ template , int> = 0> _CONSTEXPR20 explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, pair<_First, _Second>&& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} +#ifdef __cpp_lib_reference_from_temporary + template , int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) + tuple(allocator_arg_t, const _Alloc&, pair<_First, _Second>&&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #if _HAS_CXX23 template ) tuple(allocator_arg_t, const _Alloc& _Al, const pair<_First, _Second>&& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} +#ifdef __cpp_lib_reference_from_temporary + template , int> = 0> + requires _Tuple_reference_constructs_from_temporary + explicit(_Tuple_conditional_explicit_v) + tuple(allocator_arg_t, const _Alloc&, const pair<_First, _Second>&&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #ifdef __EDG__ // TRANSITION, VSO-1900279 template , int> = 0> @@ -533,6 +691,15 @@ public: tuple(allocator_arg_t, const _Alloc& _Al, _Other&& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD forward<_Other>(_Right)) { } +#ifdef __cpp_lib_reference_from_temporary + template _Other> + requires _Tuple_like_non_subrange<_Other> && (1 + sizeof...(_Rest) == tuple_size_v>) + && _Can_construct_values_from_tuple_like_v + && (sizeof...(_Rest) != 0 + || (!is_convertible_v<_Other, _This> && !is_constructible_v<_This, _Other>) ) + && _Tuple_reference_constructs_from_temporary_for_tuple_like + explicit(_Is_tuple_like_constructor_explicit_v<_Other>) tuple(allocator_arg_t, const _Alloc&, _Other&&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 tuple& operator=(const volatile tuple&) = delete; @@ -1093,6 +1260,12 @@ template #endif // ^^^ !_HAS_CXX20 ^^^ _NODISCARD constexpr _Ty make_from_tuple(_Tuple&& _Tpl) noexcept(noexcept(_STD _Make_from_tuple_impl<_Ty>( _STD forward<_Tuple>(_Tpl), make_index_sequence>>{}))) /* strengthened */ { +#ifdef __cpp_lib_reference_from_temporary + if constexpr (tuple_size_v> == 1) { + static_assert(!reference_constructs_from_temporary_v<_Ty, decltype(_STD get<0>(_STD forward<_Tuple>(_Tpl)))>, + "Cannot bind a temporary to the returned reference which will always be dangling (N5014 [tuple.apply]/2)."); + } +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ // construct _Ty from the elements of _Tpl return _STD _Make_from_tuple_impl<_Ty>( _STD forward<_Tuple>(_Tpl), make_index_sequence>>{}); diff --git a/stl/inc/type_traits b/stl/inc/type_traits index 5b2b160f973..57d105c40dd 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -748,6 +748,47 @@ _EXPORT_STD template _NO_SPECIALIZATIONS_OF_TYPE_TRAITS constexpr bool has_unique_object_representations_v = __has_unique_object_representations(_Ty); +#ifdef __cpp_lib_reference_from_temporary +#ifdef __clang__ // TRANSITION, LLVM-114344 +template +struct _Adjust_ref_binding_source { + using type = _Ty; +}; +template + requires is_scalar_v<_Ty> || is_void_v<_Ty> +struct _Adjust_ref_binding_source<_Ty> { + using type = remove_cv_t<_Ty>; +}; +template + requires is_function_v<_Ty> && requires { typename void_t<_Ty&>; } +struct _Adjust_ref_binding_source<_Ty> { + using type = _Ty&; +}; + +template +using _Adjust_ref_binding_source_t = _Adjust_ref_binding_source<_Ty>::type; +#else // ^^^ workaround / no workaround vvv +template +using _Adjust_ref_binding_source_t = _Ty; +#endif // ^^^ no workaround ^^^ + +_EXPORT_STD template +struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS reference_constructs_from_temporary + : bool_constant<__reference_constructs_from_temporary(_Ty, _Adjust_ref_binding_source_t<_Uty>)> {}; + +_EXPORT_STD template +_NO_SPECIALIZATIONS_OF_TYPE_TRAITS constexpr bool reference_constructs_from_temporary_v = + __reference_constructs_from_temporary(_Ty, _Adjust_ref_binding_source_t<_Uty>); + +_EXPORT_STD template +struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS reference_converts_from_temporary + : bool_constant<__reference_converts_from_temporary(_Ty, _Adjust_ref_binding_source_t<_Uty>)> {}; + +_EXPORT_STD template +_NO_SPECIALIZATIONS_OF_TYPE_TRAITS constexpr bool reference_converts_from_temporary_v = + __reference_converts_from_temporary(_Ty, _Adjust_ref_binding_source_t<_Uty>); +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ + #ifdef __EDG__ // TRANSITION, VSO-1690654 template struct _Is_aggregate_impl : bool_constant<__is_aggregate(_Ty)> {}; @@ -1823,9 +1864,17 @@ struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS is_nothrow_convertible template struct _Invoke_convertible : false_type {}; +#ifdef __cpp_lib_reference_from_temporary +template +using _Not_reference_converts_from_temporary = bool_constant>; +#else // ^^^ defined(__cpp_lib_reference_from_temporary) / !defined(__cpp_lib_reference_from_temporary) vvv +template +using _Not_reference_converts_from_temporary = true_type; +#endif // ^^^ !defined(__cpp_lib_reference_from_temporary) ^^^ + template struct _Invoke_convertible<_From, _To, void_t(_STD _Returns_exactly<_From>()))>> - : true_type {}; + : _Not_reference_converts_from_temporary<_To, _From> {}; template struct _Invoke_nothrow_convertible diff --git a/stl/inc/utility b/stl/inc/utility index d1e0b4238bd..6c2ec4336cd 100644 --- a/stl/inc/utility +++ b/stl/inc/utility @@ -275,6 +275,14 @@ struct pair { // store a pair of values is_nothrow_constructible_v<_Ty1, _Other1> && is_nothrow_constructible_v<_Ty2, _Other2>) // strengthened : first(_STD forward<_Other1>(_Val1)), second(_STD forward<_Other2>(_Val2)) { } +#ifdef __cpp_lib_reference_from_temporary + template , is_constructible<_Ty2, _Other2>>, int> = 0> + requires reference_constructs_from_temporary_v<_Ty1, _Other1&&> + || reference_constructs_from_temporary_v<_Ty2, _Other2&&> + explicit(!conjunction_v, is_convertible<_Other2, _Ty2>>) + pair(_Other1&&, _Other2&&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ pair(const pair&) = default; pair(pair&&) = default; @@ -286,6 +294,14 @@ struct pair { // store a pair of values pair(pair<_Other1, _Other2>& _Right) noexcept( is_nothrow_constructible_v<_Ty1, _Other1&> && is_nothrow_constructible_v<_Ty2, _Other2&>) // strengthened : first(_Right.first), second(_Right.second) {} +#ifdef __cpp_lib_reference_from_temporary + template + requires is_constructible_v<_Ty1, _Other1&> && is_constructible_v<_Ty2, _Other2&> + && (reference_constructs_from_temporary_v<_Ty1, _Other1&> + || reference_constructs_from_temporary_v<_Ty2, _Other2&>) + explicit(!conjunction_v, is_convertible<_Other2&, _Ty2>>) + pair(pair<_Other1, _Other2>&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template && is_nothrow_constructible_v<_Ty2, const _Other2&>) // strengthened : first(_Right.first), second(_Right.second) {} +#ifdef __cpp_lib_reference_from_temporary + template , is_constructible<_Ty2, const _Other2&>>, + int> = 0> + requires reference_constructs_from_temporary_v<_Ty1, const _Other1&> + || reference_constructs_from_temporary_v<_Ty2, const _Other2&> + explicit(!conjunction_v, is_convertible>) + pair(const pair<_Other1, _Other2>&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ template , is_constructible<_Ty2, _Other2>>, int> = 0> @@ -303,6 +328,14 @@ struct pair { // store a pair of values pair(pair<_Other1, _Other2>&& _Right) noexcept( is_nothrow_constructible_v<_Ty1, _Other1> && is_nothrow_constructible_v<_Ty2, _Other2>) // strengthened : first(_STD forward<_Other1>(_Right.first)), second(_STD forward<_Other2>(_Right.second)) {} +#ifdef __cpp_lib_reference_from_temporary + template , is_constructible<_Ty2, _Other2>>, int> = 0> + requires reference_constructs_from_temporary_v<_Ty1, _Other1&&> + || reference_constructs_from_temporary_v<_Ty2, _Other2&&> + explicit(!conjunction_v, is_convertible<_Other2, _Ty2>>) + pair(pair<_Other1, _Other2>&&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #if _HAS_CXX23 template @@ -312,6 +345,14 @@ struct pair { // store a pair of values noexcept(is_nothrow_constructible_v<_Ty1, const _Other1> && is_nothrow_constructible_v<_Ty2, const _Other2>) // strengthened : first(_STD forward(_Right.first)), second(_STD forward(_Right.second)) {} +#ifdef __cpp_lib_reference_from_temporary + template + requires is_constructible_v<_Ty1, const _Other1> && is_constructible_v<_Ty2, const _Other2> + && (reference_constructs_from_temporary_v<_Ty1, const _Other1 &&> + || reference_constructs_from_temporary_v<_Ty2, const _Other2 &&>) + explicit(!conjunction_v, is_convertible>) + pair(const pair<_Other1, _Other2>&&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #ifdef __EDG__ // TRANSITION, VSO-1900279 template , int> = 0> @@ -326,6 +367,15 @@ struct pair { // store a pair of values && is_nothrow_constructible_v<_Ty2, decltype(_STD get<1>(_STD declval<_Other>()))>) // strengthened : first(_STD get<0>(_STD forward<_Other>(_Right))), second(_STD get<1>(_STD forward<_Other>(_Right))) { } +#ifdef __cpp_lib_reference_from_temporary + template <_Pair_like_non_subrange _Other> + requires conjunction_v(_STD declval<_Other>()))>, + is_constructible<_Ty2, decltype(_STD get<1>(_STD declval<_Other>()))>> + && (reference_constructs_from_temporary_v<_Ty1, decltype(_STD get<0>(_STD declval<_Other>()))> + || reference_constructs_from_temporary_v<_Ty2, decltype(_STD get<1>(_STD declval<_Other>()))>) + explicit(!conjunction_v(_STD declval<_Other>())), _Ty1>, + is_convertible(_STD declval<_Other>())), _Ty2>>) pair(_Other&&) = delete; +#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^ #endif // _HAS_CXX23 template diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index d10bf011a2b..3c47c895c05 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -364,6 +364,8 @@ // P2165R4 Compatibility Between tuple, pair, And tuple-like Objects // P2166R1 Prohibiting basic_string And basic_string_view Construction From nullptr // P2186R2 Removing Garbage Collection Support +// P2255R2 Type Traits To Detect References Binding To Temporaries +// (for Clang only) // P2273R3 constexpr unique_ptr // P2278R4 cbegin Should Always Return A Constant Iterator // P2286R8 Formatting Ranges @@ -1829,28 +1831,34 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_is_implicit_lifetime 202302L #endif // ^^^ no workaround ^^^ -#define __cpp_lib_is_scoped_enum 202011L -#define __cpp_lib_mdspan 202207L -#define __cpp_lib_move_only_function 202110L -#define __cpp_lib_out_ptr 202311L -#define __cpp_lib_print 202406L -#define __cpp_lib_ranges_as_const 202311L -#define __cpp_lib_ranges_as_rvalue 202207L -#define __cpp_lib_ranges_cartesian_product 202207L -#define __cpp_lib_ranges_chunk 202202L -#define __cpp_lib_ranges_chunk_by 202202L -#define __cpp_lib_ranges_contains 202207L -#define __cpp_lib_ranges_enumerate 202302L -#define __cpp_lib_ranges_find_last 202207L -#define __cpp_lib_ranges_fold 202207L -#define __cpp_lib_ranges_iota 202202L -#define __cpp_lib_ranges_join_with 202202L -#define __cpp_lib_ranges_repeat 202207L -#define __cpp_lib_ranges_slide 202202L -#define __cpp_lib_ranges_starts_ends_with 202106L -#define __cpp_lib_ranges_stride 202207L -#define __cpp_lib_ranges_to_container 202202L -#define __cpp_lib_ranges_zip 202110L +#define __cpp_lib_is_scoped_enum 202011L +#define __cpp_lib_mdspan 202207L +#define __cpp_lib_move_only_function 202110L +#define __cpp_lib_out_ptr 202311L +#define __cpp_lib_print 202406L +#define __cpp_lib_ranges_as_const 202311L +#define __cpp_lib_ranges_as_rvalue 202207L +#define __cpp_lib_ranges_cartesian_product 202207L +#define __cpp_lib_ranges_chunk 202202L +#define __cpp_lib_ranges_chunk_by 202202L +#define __cpp_lib_ranges_contains 202207L +#define __cpp_lib_ranges_enumerate 202302L +#define __cpp_lib_ranges_find_last 202207L +#define __cpp_lib_ranges_fold 202207L +#define __cpp_lib_ranges_iota 202202L +#define __cpp_lib_ranges_join_with 202202L +#define __cpp_lib_ranges_repeat 202207L +#define __cpp_lib_ranges_slide 202202L +#define __cpp_lib_ranges_starts_ends_with 202106L +#define __cpp_lib_ranges_stride 202207L +#define __cpp_lib_ranges_to_container 202202L +#define __cpp_lib_ranges_zip 202110L + +// TRANSITION, MSVC and EDG haven't implemented intrinsics needed for P2255R2. +#if defined(__clang__) && !defined(__EDG__) +#define __cpp_lib_reference_from_temporary 202202L +#endif // ^^^ no workaround ^^^ + #define __cpp_lib_spanstream 202106L #define __cpp_lib_stacktrace 202011L #define __cpp_lib_stdatomic_h 202011L diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index edf67dce1fb..449e5d5e8f2 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -156,6 +156,10 @@ std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate.pass std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate_overaligned_request.pass.cpp FAIL std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_deallocate_matches_allocate.pass.cpp FAIL +# libc++ hasn't completely implemented P2255R2 "Type Traits To Detect References Binding To Temporaries" +std/utilities/meta/meta.rel/is_invocable_r.compile.pass.cpp:2 FAIL +std/utilities/meta/meta.rel/is_invocable_r_v.compile.pass.cpp:2 FAIL + # libc++ is missing various Ranges DRs std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp FAIL std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp FAIL @@ -562,9 +566,12 @@ std/containers/container.adaptors/flat.set/types.compile.pass.cpp FAIL std/language.support/support.limits/support.limits.general/flat_set.version.compile.pass.cpp FAIL # P2255R2 "Type Traits To Detect References Binding To Temporaries" +# (type_traits.version.compile.pass.cpp still fails for Clang due to LLVM-48860) std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp FAIL -std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp FAIL -std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp FAIL +std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp:0 FAIL +std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp:1 FAIL +std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp:0 FAIL +std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp:1 FAIL std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp:0 FAIL std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp:1 FAIL diff --git a/tests/std/test.lst b/tests/std/test.lst index 2cdac46d848..26b78e58423 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -636,6 +636,10 @@ tests\P2165R4_tuple_like_pair tests\P2165R4_tuple_like_relational_operators tests\P2165R4_tuple_like_tuple_members tests\P2231R1_complete_constexpr_optional_variant +tests\P2255R2_invocation +tests\P2255R2_reference_constructs_from_temporary +tests\P2255R2_reference_converts_from_temporary +tests\P2255R2_tuple_pair_construction tests\P2273R3_constexpr_unique_ptr tests\P2278R4_basic_const_iterator tests\P2278R4_const_span diff --git a/tests/std/tests/P2255R2_invocation/env.lst b/tests/std/tests/P2255R2_invocation/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P2255R2_invocation/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P2255R2_invocation/test.compile.pass.cpp b/tests/std/tests/P2255R2_invocation/test.compile.pass.cpp new file mode 100644 index 00000000000..caf1e348283 --- /dev/null +++ b/tests/std/tests/P2255R2_invocation/test.compile.pass.cpp @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include + +using namespace std; + +// TRANSITION, MSVC and EDG haven't implemented intrinsics needed for P2255R2. +#ifdef __cpp_lib_reference_from_temporary +struct LvalueTempFunctor { + int operator()() const& noexcept; + const int& operator()() const&& noexcept; +}; + +static_assert(is_invocable_r_v); +static_assert(!is_invocable_r_v); +static_assert(!is_invocable_r_v); +static_assert(!is_invocable_r_v); +static_assert(is_invocable_r_v); +static_assert(is_invocable_r_v); +static_assert(!is_invocable_r_v); + +static_assert(is_constructible_v, int& (*) ()>); +static_assert(!is_constructible_v, short& (*) ()>); +static_assert(!is_constructible_v, int (*)()>); +static_assert(!is_constructible_v, LvalueTempFunctor>); + +static_assert(is_constructible_v, int& (*) ()>); +static_assert(!is_constructible_v, short& (*) ()>); +static_assert(!is_constructible_v, int (*)()>); + +static_assert(is_constructible_v, int& (*) ()>); +static_assert(!is_constructible_v, short& (*) ()>); +static_assert(!is_constructible_v, int (*)()>); + +static_assert(!is_constructible_v, LvalueTempFunctor>); +static_assert(!is_constructible_v, LvalueTempFunctor>); +static_assert(is_constructible_v, LvalueTempFunctor>); +static_assert(is_constructible_v, LvalueTempFunctor>); + +#ifdef __cpp_noexcept_function_type +static_assert(is_nothrow_invocable_r_v); +static_assert(!is_nothrow_invocable_r_v); +static_assert(!is_nothrow_invocable_r_v); +static_assert(!is_nothrow_invocable_r_v); +static_assert(is_nothrow_invocable_r_v); +static_assert(is_nothrow_invocable_r_v); +static_assert(!is_nothrow_invocable_r_v); + +static_assert(is_constructible_v, int& (*) () noexcept>); +static_assert(!is_constructible_v, short& (*) () noexcept>); +static_assert(!is_constructible_v, int (*)() noexcept>); + +static_assert(is_constructible_v, int& (*) () noexcept>); +static_assert(!is_constructible_v, short& (*) () noexcept>); +static_assert(!is_constructible_v, int (*)() noexcept>); + +static_assert(!is_constructible_v, LvalueTempFunctor>); +static_assert(!is_constructible_v, LvalueTempFunctor>); +static_assert(is_constructible_v, LvalueTempFunctor>); +static_assert(is_constructible_v, LvalueTempFunctor>); +#endif // defined(__cpp_noexcept_function_type) +#endif // ^^^ no workaround ^^^ diff --git a/tests/std/tests/P2255R2_reference_constructs_from_temporary/env.lst b/tests/std/tests/P2255R2_reference_constructs_from_temporary/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P2255R2_reference_constructs_from_temporary/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P2255R2_reference_constructs_from_temporary/test.compile.pass.cpp b/tests/std/tests/P2255R2_reference_constructs_from_temporary/test.compile.pass.cpp new file mode 100644 index 00000000000..1e2d1fa4a19 --- /dev/null +++ b/tests/std/tests/P2255R2_reference_constructs_from_temporary/test.compile.pass.cpp @@ -0,0 +1,204 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +using namespace std; + +// TRANSITION, MSVC and EDG haven't implemented intrinsics needed for P2255R2. +#ifdef __cpp_lib_reference_from_temporary +enum class conv_explicitly : bool { + no, + yes, +}; + +template +struct to_int_lvalue { + explicit(static_cast(Explicitly)) operator int&() const; +}; + +template +struct to_int_xvalue { + explicit(static_cast(Explicitly)) operator int&&() const; +}; + +template +struct to_int_prvalue { + explicit(static_cast(Explicitly)) operator int() const; +}; + +template +void test_one_non_temporary_bindable_type() { + static_assert(!reference_constructs_from_temporary::value); + + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + + static_assert(!reference_constructs_from_temporary_v); + + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); +} + +void test_non_temporary_bindable_types() { + test_one_non_temporary_bindable_type(); + + test_one_non_temporary_bindable_type(); + test_one_non_temporary_bindable_type(); + + test_one_non_temporary_bindable_type(); + test_one_non_temporary_bindable_type>(); + + test_one_non_temporary_bindable_type(); + test_one_non_temporary_bindable_type&>(); + + test_one_non_temporary_bindable_type(); + test_one_non_temporary_bindable_type&>(); + + test_one_non_temporary_bindable_type(); + test_one_non_temporary_bindable_type(); +} + +template +void test_one_cvref_to_object() { + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(reference_constructs_from_temporary::value); + static_assert(reference_constructs_from_temporary::value); + static_assert(reference_constructs_from_temporary::value == is_scalar_v); + static_assert(reference_constructs_from_temporary::value == is_scalar_v); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + static_assert(!reference_constructs_from_temporary::value); + + static_assert(reference_constructs_from_temporary::value); + static_assert(reference_constructs_from_temporary::value == is_scalar_v); + static_assert(reference_constructs_from_temporary::value == is_scalar_v); + static_assert(reference_constructs_from_temporary::value == is_scalar_v); + static_assert(reference_constructs_from_temporary::value); + static_assert(reference_constructs_from_temporary::value); + static_assert(reference_constructs_from_temporary::value == is_scalar_v); + static_assert(reference_constructs_from_temporary::value == is_scalar_v); + static_assert(reference_constructs_from_temporary::value); + static_assert(reference_constructs_from_temporary::value == is_scalar_v); + static_assert(reference_constructs_from_temporary::value); + static_assert(reference_constructs_from_temporary::value == is_scalar_v); + static_assert(reference_constructs_from_temporary::value); + static_assert(reference_constructs_from_temporary::value); + static_assert(reference_constructs_from_temporary::value); + static_assert(reference_constructs_from_temporary::value); + + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(reference_constructs_from_temporary_v); + static_assert(reference_constructs_from_temporary_v); + static_assert(reference_constructs_from_temporary_v == is_scalar_v); + static_assert(reference_constructs_from_temporary_v == is_scalar_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + static_assert(!reference_constructs_from_temporary_v); + + static_assert(reference_constructs_from_temporary_v); + static_assert(reference_constructs_from_temporary_v == is_scalar_v); + static_assert(reference_constructs_from_temporary_v == is_scalar_v); + static_assert(reference_constructs_from_temporary_v == is_scalar_v); + static_assert(reference_constructs_from_temporary_v); + static_assert(reference_constructs_from_temporary_v); + static_assert(reference_constructs_from_temporary_v == is_scalar_v); + static_assert(reference_constructs_from_temporary_v == is_scalar_v); + static_assert(reference_constructs_from_temporary_v); + static_assert(reference_constructs_from_temporary_v == is_scalar_v); + static_assert(reference_constructs_from_temporary_v); + static_assert(reference_constructs_from_temporary_v == is_scalar_v); + static_assert(reference_constructs_from_temporary_v); + static_assert(reference_constructs_from_temporary_v); + static_assert(reference_constructs_from_temporary_v); + static_assert(reference_constructs_from_temporary_v); +} + +void test_object_types() { + test_one_cvref_to_object(); + test_one_cvref_to_object(); + test_one_cvref_to_object>(); + test_one_cvref_to_object>(); + test_one_cvref_to_object>(); + test_one_cvref_to_object>(); +} + +template +void test_to_int_ref() { + static_assert(!reference_constructs_from_temporary>::value); + static_assert(!reference_constructs_from_temporary>::value); + static_assert(reference_constructs_from_temporary>::value + == !static_cast(Explicitly)); + static_assert(!reference_constructs_from_temporary>::value); + static_assert(!reference_constructs_from_temporary>::value); + static_assert(reference_constructs_from_temporary>::value + == !static_cast(Explicitly)); + static_assert(!reference_constructs_from_temporary>::value); + static_assert(reference_constructs_from_temporary>::value); + static_assert(reference_constructs_from_temporary>::value + == !static_cast(Explicitly)); + + static_assert(!reference_constructs_from_temporary_v>); + static_assert(!reference_constructs_from_temporary_v>); + static_assert(reference_constructs_from_temporary_v> + == !static_cast(Explicitly)); + static_assert(!reference_constructs_from_temporary_v>); + static_assert(!reference_constructs_from_temporary_v>); + static_assert(reference_constructs_from_temporary_v> + == !static_cast(Explicitly)); + + static_assert(!reference_constructs_from_temporary_v>); + static_assert(reference_constructs_from_temporary_v>); + static_assert(reference_constructs_from_temporary_v> + == !static_cast(Explicitly)); +} + +void test_to_int_ref_all() { + test_to_int_ref(); + test_to_int_ref(); +} +#endif // ^^^ no workaround ^^^ diff --git a/tests/std/tests/P2255R2_reference_converts_from_temporary/env.lst b/tests/std/tests/P2255R2_reference_converts_from_temporary/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P2255R2_reference_converts_from_temporary/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P2255R2_reference_converts_from_temporary/test.compile.pass.cpp b/tests/std/tests/P2255R2_reference_converts_from_temporary/test.compile.pass.cpp new file mode 100644 index 00000000000..bd6e916c64f --- /dev/null +++ b/tests/std/tests/P2255R2_reference_converts_from_temporary/test.compile.pass.cpp @@ -0,0 +1,206 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +using namespace std; + +// TRANSITION, MSVC and EDG haven't implemented intrinsics needed for P2255R2. +#ifdef __cpp_lib_reference_from_temporary +enum class conv_explicitly : bool { + no, + yes, +}; + +template +struct to_int_lvalue { + explicit(static_cast(Explicitly)) operator int&() const; +}; + +template +struct to_int_xvalue { + explicit(static_cast(Explicitly)) operator int&&() const; +}; + +template +struct to_int_prvalue { + explicit(static_cast(Explicitly)) operator int() const; +}; + +template +void test_one_non_temporary_bindable_type() { + static_assert(!reference_converts_from_temporary::value); + + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + + static_assert(!reference_converts_from_temporary_v); + + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); +} + +void test_non_temporary_bindable_types() { + test_one_non_temporary_bindable_type(); + + test_one_non_temporary_bindable_type(); + test_one_non_temporary_bindable_type(); + + test_one_non_temporary_bindable_type(); + test_one_non_temporary_bindable_type>(); + + test_one_non_temporary_bindable_type(); + test_one_non_temporary_bindable_type&>(); + + test_one_non_temporary_bindable_type(); + test_one_non_temporary_bindable_type&>(); + + test_one_non_temporary_bindable_type(); + test_one_non_temporary_bindable_type(); +} + +template +void test_one_cvref_to_object() { + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(reference_converts_from_temporary::value); + static_assert(reference_converts_from_temporary::value); + static_assert(reference_converts_from_temporary::value == is_scalar_v); + static_assert(reference_converts_from_temporary::value == is_scalar_v); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + static_assert(!reference_converts_from_temporary::value); + + static_assert(reference_converts_from_temporary::value); + static_assert(reference_converts_from_temporary::value == is_scalar_v); + static_assert(reference_converts_from_temporary::value == is_scalar_v); + static_assert(reference_converts_from_temporary::value == is_scalar_v); + static_assert(reference_converts_from_temporary::value); + static_assert(reference_converts_from_temporary::value); + static_assert(reference_converts_from_temporary::value == is_scalar_v); + static_assert(reference_converts_from_temporary::value == is_scalar_v); + static_assert(reference_converts_from_temporary::value); + static_assert(reference_converts_from_temporary::value == is_scalar_v); + static_assert(reference_converts_from_temporary::value); + static_assert(reference_converts_from_temporary::value == is_scalar_v); + static_assert(reference_converts_from_temporary::value); + static_assert(reference_converts_from_temporary::value); + static_assert(reference_converts_from_temporary::value); + static_assert(reference_converts_from_temporary::value); + + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(reference_converts_from_temporary_v); + static_assert(reference_converts_from_temporary_v); + static_assert(reference_converts_from_temporary_v == is_scalar_v); + static_assert(reference_converts_from_temporary_v == is_scalar_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + static_assert(!reference_converts_from_temporary_v); + + static_assert(reference_converts_from_temporary_v); + static_assert(reference_converts_from_temporary_v == is_scalar_v); + static_assert(reference_converts_from_temporary_v == is_scalar_v); + static_assert(reference_converts_from_temporary_v == is_scalar_v); + static_assert(reference_converts_from_temporary_v); + static_assert(reference_converts_from_temporary_v); + static_assert(reference_converts_from_temporary_v == is_scalar_v); + static_assert(reference_converts_from_temporary_v == is_scalar_v); + static_assert(reference_converts_from_temporary_v); + static_assert(reference_converts_from_temporary_v == is_scalar_v); + static_assert(reference_converts_from_temporary_v); + static_assert(reference_converts_from_temporary_v == is_scalar_v); + static_assert(reference_converts_from_temporary_v); + static_assert(reference_converts_from_temporary_v); + static_assert(reference_converts_from_temporary_v); + static_assert(reference_converts_from_temporary_v); +} + +void test_object_types() { + test_one_cvref_to_object(); + test_one_cvref_to_object(); + test_one_cvref_to_object>(); + test_one_cvref_to_object>(); + test_one_cvref_to_object>(); + test_one_cvref_to_object>(); +} + +template +void test_to_int_ref() { + static_assert(!reference_converts_from_temporary>::value); + static_assert(!reference_converts_from_temporary>::value); + static_assert(reference_converts_from_temporary>::value + == !static_cast(Explicitly)); + static_assert(!reference_converts_from_temporary>::value); + static_assert(!reference_converts_from_temporary>::value); + static_assert(reference_converts_from_temporary>::value + == !static_cast(Explicitly)); + static_assert(!reference_converts_from_temporary>::value); + static_assert(reference_converts_from_temporary>::value + == !static_cast(Explicitly)); + static_assert(reference_converts_from_temporary>::value + == !static_cast(Explicitly)); + + static_assert(!reference_converts_from_temporary_v>); + static_assert(!reference_converts_from_temporary_v>); + static_assert( + reference_converts_from_temporary_v> == !static_cast(Explicitly)); + static_assert(!reference_converts_from_temporary_v>); + static_assert(!reference_converts_from_temporary_v>); + static_assert( + reference_converts_from_temporary_v> == !static_cast(Explicitly)); + + static_assert(!reference_converts_from_temporary_v>); + static_assert( + reference_converts_from_temporary_v> == !static_cast(Explicitly)); + static_assert( + reference_converts_from_temporary_v> == !static_cast(Explicitly)); +} + +void test_to_int_ref_all() { + test_to_int_ref(); + test_to_int_ref(); +} +#endif // ^^^ no workaround ^^^ diff --git a/tests/std/tests/P2255R2_tuple_pair_construction/env.lst b/tests/std/tests/P2255R2_tuple_pair_construction/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P2255R2_tuple_pair_construction/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P2255R2_tuple_pair_construction/test.compile.pass.cpp b/tests/std/tests/P2255R2_tuple_pair_construction/test.compile.pass.cpp new file mode 100644 index 00000000000..4e19495b8c5 --- /dev/null +++ b/tests/std/tests/P2255R2_tuple_pair_construction/test.compile.pass.cpp @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include + +using namespace std; + +// TRANSITION, MSVC and EDG haven't implemented intrinsics needed for P2255R2. +#ifdef __cpp_lib_reference_from_temporary +template +void assert_constref_constructible_single() { + static_assert(is_constructible_v == Expected); + static_assert(is_constructible_v == Expected); + static_assert(is_constructible_v == Expected); + static_assert(is_constructible_v == Expected); + if constexpr (sizeof...(Args) == 2) { + static_assert(is_constructible_v&> == Expected); + static_assert(is_constructible_v&> == Expected); + static_assert(is_constructible_v> == Expected); + static_assert(is_constructible_v> == Expected); + } + static_assert(is_constructible_v&> == Expected); + static_assert(is_constructible_v&> == Expected); + static_assert(is_constructible_v> == Expected); + static_assert(is_constructible_v> == Expected); +} + +template +void assert_mutref_constructible_single() { + static_assert(is_constructible_v == Expected); + if constexpr (sizeof...(Args) == 2) { + static_assert(is_constructible_v> == Expected); + } + static_assert(is_constructible_v> == Expected); +} + +void assert_normal_constructible() { + assert_constref_constructible_single, int>(); + assert_constref_constructible_single, long>(); + + assert_constref_constructible_single, int, int>(); + assert_constref_constructible_single, long, int>(); + assert_constref_constructible_single, long, long>(); + + assert_constref_constructible_single, int, int>(); + assert_constref_constructible_single, long, int>(); + assert_constref_constructible_single, int, long>(); + + assert_mutref_constructible_single, int>(); + assert_mutref_constructible_single, long>(); + + assert_mutref_constructible_single, int, int>(); + assert_mutref_constructible_single, long, int>(); + assert_mutref_constructible_single, long, long>(); + + assert_mutref_constructible_single, int, int>(); + assert_mutref_constructible_single, long, int>(); + assert_mutref_constructible_single, int, long>(); +} + +struct LvalueTempConverter { + operator int() &; + operator int&&() &&; + operator const int&() &&; +}; + +template +void assert_lvalue_temp_converter_single() { + static_assert(!is_constructible_v); + static_assert(is_constructible_v); + if constexpr (sizeof...(Args) == 1) { + static_assert(!is_constructible_v>); + static_assert(is_constructible_v>); + } + static_assert(!is_constructible_v>); + static_assert(is_constructible_v>); +} + +void assert_lvalue_temp_converter() { + assert_lvalue_temp_converter_single>(); + assert_lvalue_temp_converter_single>(); + + assert_lvalue_temp_converter_single, const int&>(); + assert_lvalue_temp_converter_single, int&&>(); + + assert_lvalue_temp_converter_single, const int&>(); + assert_lvalue_temp_converter_single, int&&>(); +} +#endif // ^^^ no workaround ^^^ diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 9402abdf299..1f88a25ff9c 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -837,6 +837,12 @@ STATIC_ASSERT(__cpp_lib_raw_memory_algorithms == 201606L); #error __cpp_lib_raw_memory_algorithms is defined #endif +#if _HAS_CXX23 && defined(__clang__) // TRANSITION, MSVC and EDG haven't implemented intrinsics needed for P2255R2. +STATIC_ASSERT(__cpp_lib_reference_from_temporary == 202202L); +#elif defined(__cpp_lib_reference_from_temporary) +#error __cpp_lib_reference_from_temporary is defined +#endif + #if _HAS_CXX20 STATIC_ASSERT(__cpp_lib_remove_cvref == 201711L); #elif defined(__cpp_lib_remove_cvref)