Skip to content

Commit 395e9a6

Browse files
Implement P2255R2 Type Traits To Detect References Binding To Temporaries for Clang (#5537)
Co-authored-by: Stephan T. Lavavej <[email protected]>
1 parent 48db51b commit 395e9a6

File tree

16 files changed

+908
-25
lines changed

16 files changed

+908
-25
lines changed

stl/inc/memory

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3475,6 +3475,11 @@ public:
34753475
}
34763476

34773477
_NODISCARD _CONSTEXPR23 add_lvalue_reference_t<_Ty> operator*() const noexcept(noexcept(*_STD declval<pointer>())) {
3478+
#ifdef __cpp_lib_reference_from_temporary
3479+
static_assert(
3480+
!reference_converts_from_temporary_v<add_lvalue_reference_t<_Ty>, decltype(*_STD declval<pointer>())>,
3481+
"Can't return a temporary object from unique_ptr::operator*(). (N5014 [unique.ptr.single.observers]/1)");
3482+
#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^
34783483
return *_Mypair._Myval2;
34793484
}
34803485

stl/inc/tuple

Lines changed: 173 additions & 0 deletions
Large diffs are not rendered by default.

stl/inc/type_traits

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,47 @@ _EXPORT_STD template <class _Ty>
748748
_NO_SPECIALIZATIONS_OF_TYPE_TRAITS constexpr bool has_unique_object_representations_v =
749749
__has_unique_object_representations(_Ty);
750750

751+
#ifdef __cpp_lib_reference_from_temporary
752+
#ifdef __clang__ // TRANSITION, LLVM-114344
753+
template <class _Ty>
754+
struct _Adjust_ref_binding_source {
755+
using type = _Ty;
756+
};
757+
template <class _Ty>
758+
requires is_scalar_v<_Ty> || is_void_v<_Ty>
759+
struct _Adjust_ref_binding_source<_Ty> {
760+
using type = remove_cv_t<_Ty>;
761+
};
762+
template <class _Ty>
763+
requires is_function_v<_Ty> && requires { typename void_t<_Ty&>; }
764+
struct _Adjust_ref_binding_source<_Ty> {
765+
using type = _Ty&;
766+
};
767+
768+
template <class _Ty>
769+
using _Adjust_ref_binding_source_t = _Adjust_ref_binding_source<_Ty>::type;
770+
#else // ^^^ workaround / no workaround vvv
771+
template <class _Ty>
772+
using _Adjust_ref_binding_source_t = _Ty;
773+
#endif // ^^^ no workaround ^^^
774+
775+
_EXPORT_STD template <class _Ty, class _Uty>
776+
struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS reference_constructs_from_temporary
777+
: bool_constant<__reference_constructs_from_temporary(_Ty, _Adjust_ref_binding_source_t<_Uty>)> {};
778+
779+
_EXPORT_STD template <class _Ty, class _Uty>
780+
_NO_SPECIALIZATIONS_OF_TYPE_TRAITS constexpr bool reference_constructs_from_temporary_v =
781+
__reference_constructs_from_temporary(_Ty, _Adjust_ref_binding_source_t<_Uty>);
782+
783+
_EXPORT_STD template <class _Ty, class _Uty>
784+
struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS reference_converts_from_temporary
785+
: bool_constant<__reference_converts_from_temporary(_Ty, _Adjust_ref_binding_source_t<_Uty>)> {};
786+
787+
_EXPORT_STD template <class _Ty, class _Uty>
788+
_NO_SPECIALIZATIONS_OF_TYPE_TRAITS constexpr bool reference_converts_from_temporary_v =
789+
__reference_converts_from_temporary(_Ty, _Adjust_ref_binding_source_t<_Uty>);
790+
#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^
791+
751792
#ifdef __EDG__ // TRANSITION, VSO-1690654
752793
template <class _Ty>
753794
struct _Is_aggregate_impl : bool_constant<__is_aggregate(_Ty)> {};
@@ -1823,9 +1864,17 @@ struct _NO_SPECIALIZATIONS_OF_TYPE_TRAITS is_nothrow_convertible
18231864
template <class _From, class _To, class = void>
18241865
struct _Invoke_convertible : false_type {};
18251866

1867+
#ifdef __cpp_lib_reference_from_temporary
1868+
template <class _To, class _From>
1869+
using _Not_reference_converts_from_temporary = bool_constant<!reference_converts_from_temporary_v<_To, _From>>;
1870+
#else // ^^^ defined(__cpp_lib_reference_from_temporary) / !defined(__cpp_lib_reference_from_temporary) vvv
1871+
template <class _To, class _From>
1872+
using _Not_reference_converts_from_temporary = true_type;
1873+
#endif // ^^^ !defined(__cpp_lib_reference_from_temporary) ^^^
1874+
18261875
template <class _From, class _To>
18271876
struct _Invoke_convertible<_From, _To, void_t<decltype(_STD _Fake_copy_init<_To>(_STD _Returns_exactly<_From>()))>>
1828-
: true_type {};
1877+
: _Not_reference_converts_from_temporary<_To, _From> {};
18291878

18301879
template <class _From, class _To>
18311880
struct _Invoke_nothrow_convertible

stl/inc/utility

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,14 @@ struct pair { // store a pair of values
275275
is_nothrow_constructible_v<_Ty1, _Other1> && is_nothrow_constructible_v<_Ty2, _Other2>) // strengthened
276276
: first(_STD forward<_Other1>(_Val1)), second(_STD forward<_Other2>(_Val2)) {
277277
}
278+
#ifdef __cpp_lib_reference_from_temporary
279+
template <class _Other1 = _Ty1, class _Other2 = _Ty2,
280+
enable_if_t<conjunction_v<is_constructible<_Ty1, _Other1>, is_constructible<_Ty2, _Other2>>, int> = 0>
281+
requires reference_constructs_from_temporary_v<_Ty1, _Other1&&>
282+
|| reference_constructs_from_temporary_v<_Ty2, _Other2&&>
283+
explicit(!conjunction_v<is_convertible<_Other1, _Ty1>, is_convertible<_Other2, _Ty2>>)
284+
pair(_Other1&&, _Other2&&) = delete;
285+
#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^
278286

279287
pair(const pair&) = default;
280288
pair(pair&&) = default;
@@ -286,6 +294,14 @@ struct pair { // store a pair of values
286294
pair(pair<_Other1, _Other2>& _Right) noexcept(
287295
is_nothrow_constructible_v<_Ty1, _Other1&> && is_nothrow_constructible_v<_Ty2, _Other2&>) // strengthened
288296
: first(_Right.first), second(_Right.second) {}
297+
#ifdef __cpp_lib_reference_from_temporary
298+
template <class _Other1, class _Other2>
299+
requires is_constructible_v<_Ty1, _Other1&> && is_constructible_v<_Ty2, _Other2&>
300+
&& (reference_constructs_from_temporary_v<_Ty1, _Other1&>
301+
|| reference_constructs_from_temporary_v<_Ty2, _Other2&>)
302+
explicit(!conjunction_v<is_convertible<_Other1&, _Ty1>, is_convertible<_Other2&, _Ty2>>)
303+
pair(pair<_Other1, _Other2>&) = delete;
304+
#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^
289305
#endif // _HAS_CXX23
290306

291307
template <class _Other1, class _Other2,
@@ -296,13 +312,30 @@ struct pair { // store a pair of values
296312
noexcept(is_nothrow_constructible_v<_Ty1, const _Other1&>
297313
&& is_nothrow_constructible_v<_Ty2, const _Other2&>) // strengthened
298314
: first(_Right.first), second(_Right.second) {}
315+
#ifdef __cpp_lib_reference_from_temporary
316+
template <class _Other1, class _Other2,
317+
enable_if_t<conjunction_v<is_constructible<_Ty1, const _Other1&>, is_constructible<_Ty2, const _Other2&>>,
318+
int> = 0>
319+
requires reference_constructs_from_temporary_v<_Ty1, const _Other1&>
320+
|| reference_constructs_from_temporary_v<_Ty2, const _Other2&>
321+
explicit(!conjunction_v<is_convertible<const _Other1&, _Ty1>, is_convertible<const _Other2&, _Ty2>>)
322+
pair(const pair<_Other1, _Other2>&) = delete;
323+
#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^
299324

300325
template <class _Other1, class _Other2,
301326
enable_if_t<conjunction_v<is_constructible<_Ty1, _Other1>, is_constructible<_Ty2, _Other2>>, int> = 0>
302327
constexpr explicit(!conjunction_v<is_convertible<_Other1, _Ty1>, is_convertible<_Other2, _Ty2>>)
303328
pair(pair<_Other1, _Other2>&& _Right) noexcept(
304329
is_nothrow_constructible_v<_Ty1, _Other1> && is_nothrow_constructible_v<_Ty2, _Other2>) // strengthened
305330
: first(_STD forward<_Other1>(_Right.first)), second(_STD forward<_Other2>(_Right.second)) {}
331+
#ifdef __cpp_lib_reference_from_temporary
332+
template <class _Other1, class _Other2,
333+
enable_if_t<conjunction_v<is_constructible<_Ty1, _Other1>, is_constructible<_Ty2, _Other2>>, int> = 0>
334+
requires reference_constructs_from_temporary_v<_Ty1, _Other1&&>
335+
|| reference_constructs_from_temporary_v<_Ty2, _Other2&&>
336+
explicit(!conjunction_v<is_convertible<_Other1, _Ty1>, is_convertible<_Other2, _Ty2>>)
337+
pair(pair<_Other1, _Other2>&&) = delete;
338+
#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^
306339

307340
#if _HAS_CXX23
308341
template <class _Other1, class _Other2>
@@ -312,6 +345,14 @@ struct pair { // store a pair of values
312345
noexcept(is_nothrow_constructible_v<_Ty1, const _Other1>
313346
&& is_nothrow_constructible_v<_Ty2, const _Other2>) // strengthened
314347
: first(_STD forward<const _Other1>(_Right.first)), second(_STD forward<const _Other2>(_Right.second)) {}
348+
#ifdef __cpp_lib_reference_from_temporary
349+
template <class _Other1, class _Other2>
350+
requires is_constructible_v<_Ty1, const _Other1> && is_constructible_v<_Ty2, const _Other2>
351+
&& (reference_constructs_from_temporary_v<_Ty1, const _Other1 &&>
352+
|| reference_constructs_from_temporary_v<_Ty2, const _Other2 &&>)
353+
explicit(!conjunction_v<is_convertible<const _Other1, _Ty1>, is_convertible<const _Other2, _Ty2>>)
354+
pair(const pair<_Other1, _Other2>&&) = delete;
355+
#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^
315356

316357
#ifdef __EDG__ // TRANSITION, VSO-1900279
317358
template <class _Other, enable_if_t<_Can_construct_from_pair_like<_Other, _Ty1, _Ty2>, int> = 0>
@@ -326,6 +367,15 @@ struct pair { // store a pair of values
326367
&& is_nothrow_constructible_v<_Ty2, decltype(_STD get<1>(_STD declval<_Other>()))>) // strengthened
327368
: first(_STD get<0>(_STD forward<_Other>(_Right))), second(_STD get<1>(_STD forward<_Other>(_Right))) {
328369
}
370+
#ifdef __cpp_lib_reference_from_temporary
371+
template <_Pair_like_non_subrange _Other>
372+
requires conjunction_v<is_constructible<_Ty1, decltype(_STD get<0>(_STD declval<_Other>()))>,
373+
is_constructible<_Ty2, decltype(_STD get<1>(_STD declval<_Other>()))>>
374+
&& (reference_constructs_from_temporary_v<_Ty1, decltype(_STD get<0>(_STD declval<_Other>()))>
375+
|| reference_constructs_from_temporary_v<_Ty2, decltype(_STD get<1>(_STD declval<_Other>()))>)
376+
explicit(!conjunction_v<is_convertible<decltype(_STD get<0>(_STD declval<_Other>())), _Ty1>,
377+
is_convertible<decltype(_STD get<1>(_STD declval<_Other>())), _Ty2>>) pair(_Other&&) = delete;
378+
#endif // ^^^ defined(__cpp_lib_reference_from_temporary) ^^^
329379
#endif // _HAS_CXX23
330380

331381
template <class... _Types1, class... _Types2>

stl/inc/yvals_core.h

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,8 @@
364364
// P2165R4 Compatibility Between tuple, pair, And tuple-like Objects
365365
// P2166R1 Prohibiting basic_string And basic_string_view Construction From nullptr
366366
// P2186R2 Removing Garbage Collection Support
367+
// P2255R2 Type Traits To Detect References Binding To Temporaries
368+
// (for Clang only)
367369
// P2273R3 constexpr unique_ptr
368370
// P2278R4 cbegin Should Always Return A Constant Iterator
369371
// P2286R8 Formatting Ranges
@@ -1829,28 +1831,34 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect
18291831
#define __cpp_lib_is_implicit_lifetime 202302L
18301832
#endif // ^^^ no workaround ^^^
18311833

1832-
#define __cpp_lib_is_scoped_enum 202011L
1833-
#define __cpp_lib_mdspan 202207L
1834-
#define __cpp_lib_move_only_function 202110L
1835-
#define __cpp_lib_out_ptr 202311L
1836-
#define __cpp_lib_print 202406L
1837-
#define __cpp_lib_ranges_as_const 202311L
1838-
#define __cpp_lib_ranges_as_rvalue 202207L
1839-
#define __cpp_lib_ranges_cartesian_product 202207L
1840-
#define __cpp_lib_ranges_chunk 202202L
1841-
#define __cpp_lib_ranges_chunk_by 202202L
1842-
#define __cpp_lib_ranges_contains 202207L
1843-
#define __cpp_lib_ranges_enumerate 202302L
1844-
#define __cpp_lib_ranges_find_last 202207L
1845-
#define __cpp_lib_ranges_fold 202207L
1846-
#define __cpp_lib_ranges_iota 202202L
1847-
#define __cpp_lib_ranges_join_with 202202L
1848-
#define __cpp_lib_ranges_repeat 202207L
1849-
#define __cpp_lib_ranges_slide 202202L
1850-
#define __cpp_lib_ranges_starts_ends_with 202106L
1851-
#define __cpp_lib_ranges_stride 202207L
1852-
#define __cpp_lib_ranges_to_container 202202L
1853-
#define __cpp_lib_ranges_zip 202110L
1834+
#define __cpp_lib_is_scoped_enum 202011L
1835+
#define __cpp_lib_mdspan 202207L
1836+
#define __cpp_lib_move_only_function 202110L
1837+
#define __cpp_lib_out_ptr 202311L
1838+
#define __cpp_lib_print 202406L
1839+
#define __cpp_lib_ranges_as_const 202311L
1840+
#define __cpp_lib_ranges_as_rvalue 202207L
1841+
#define __cpp_lib_ranges_cartesian_product 202207L
1842+
#define __cpp_lib_ranges_chunk 202202L
1843+
#define __cpp_lib_ranges_chunk_by 202202L
1844+
#define __cpp_lib_ranges_contains 202207L
1845+
#define __cpp_lib_ranges_enumerate 202302L
1846+
#define __cpp_lib_ranges_find_last 202207L
1847+
#define __cpp_lib_ranges_fold 202207L
1848+
#define __cpp_lib_ranges_iota 202202L
1849+
#define __cpp_lib_ranges_join_with 202202L
1850+
#define __cpp_lib_ranges_repeat 202207L
1851+
#define __cpp_lib_ranges_slide 202202L
1852+
#define __cpp_lib_ranges_starts_ends_with 202106L
1853+
#define __cpp_lib_ranges_stride 202207L
1854+
#define __cpp_lib_ranges_to_container 202202L
1855+
#define __cpp_lib_ranges_zip 202110L
1856+
1857+
// TRANSITION, MSVC and EDG haven't implemented intrinsics needed for P2255R2.
1858+
#if defined(__clang__) && !defined(__EDG__)
1859+
#define __cpp_lib_reference_from_temporary 202202L
1860+
#endif // ^^^ no workaround ^^^
1861+
18541862
#define __cpp_lib_spanstream 202106L
18551863
#define __cpp_lib_stacktrace 202011L
18561864
#define __cpp_lib_stdatomic_h 202011L

tests/libcxx/expected_results.txt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate.pass
156156
std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate_overaligned_request.pass.cpp FAIL
157157
std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_deallocate_matches_allocate.pass.cpp FAIL
158158

159+
# libc++ hasn't completely implemented P2255R2 "Type Traits To Detect References Binding To Temporaries"
160+
std/utilities/meta/meta.rel/is_invocable_r.compile.pass.cpp:2 FAIL
161+
std/utilities/meta/meta.rel/is_invocable_r_v.compile.pass.cpp:2 FAIL
162+
159163
# libc++ is missing various Ranges DRs
160164
std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp FAIL
161165
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
562566
std/language.support/support.limits/support.limits.general/flat_set.version.compile.pass.cpp FAIL
563567

564568
# P2255R2 "Type Traits To Detect References Binding To Temporaries"
569+
# (type_traits.version.compile.pass.cpp still fails for Clang due to LLVM-48860)
565570
std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp FAIL
566-
std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp FAIL
567-
std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp FAIL
571+
std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp:0 FAIL
572+
std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp:1 FAIL
573+
std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp:0 FAIL
574+
std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp:1 FAIL
568575
std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp:0 FAIL
569576
std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp:1 FAIL
570577

tests/std/test.lst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,10 @@ tests\P2165R4_tuple_like_pair
636636
tests\P2165R4_tuple_like_relational_operators
637637
tests\P2165R4_tuple_like_tuple_members
638638
tests\P2231R1_complete_constexpr_optional_variant
639+
tests\P2255R2_invocation
640+
tests\P2255R2_reference_constructs_from_temporary
641+
tests\P2255R2_reference_converts_from_temporary
642+
tests\P2255R2_tuple_pair_construction
639643
tests\P2273R3_constexpr_unique_ptr
640644
tests\P2278R4_basic_const_iterator
641645
tests\P2278R4_const_span
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
RUNALL_INCLUDE ..\usual_latest_matrix.lst
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#include <functional>
5+
#include <type_traits>
6+
7+
using namespace std;
8+
9+
// TRANSITION, MSVC and EDG haven't implemented intrinsics needed for P2255R2.
10+
#ifdef __cpp_lib_reference_from_temporary
11+
struct LvalueTempFunctor {
12+
int operator()() const& noexcept;
13+
const int& operator()() const&& noexcept;
14+
};
15+
16+
static_assert(is_invocable_r_v<const int&, int& (*) ()>);
17+
static_assert(!is_invocable_r_v<const int&, short& (*) ()>);
18+
static_assert(!is_invocable_r_v<const int&, int (*)()>);
19+
static_assert(!is_invocable_r_v<int&&, int (*)()>);
20+
static_assert(is_invocable_r_v<int, int (*)()>);
21+
static_assert(is_invocable_r_v<const int&, LvalueTempFunctor>);
22+
static_assert(!is_invocable_r_v<const int&, LvalueTempFunctor&>);
23+
24+
static_assert(is_constructible_v<function<const int&()>, int& (*) ()>);
25+
static_assert(!is_constructible_v<function<const int&()>, short& (*) ()>);
26+
static_assert(!is_constructible_v<function<const int&()>, int (*)()>);
27+
static_assert(!is_constructible_v<function<const int&()>, LvalueTempFunctor>);
28+
29+
static_assert(is_constructible_v<move_only_function<const int&()>, int& (*) ()>);
30+
static_assert(!is_constructible_v<move_only_function<const int&()>, short& (*) ()>);
31+
static_assert(!is_constructible_v<move_only_function<const int&()>, int (*)()>);
32+
33+
static_assert(is_constructible_v<move_only_function<const int&() const>, int& (*) ()>);
34+
static_assert(!is_constructible_v<move_only_function<const int&() const>, short& (*) ()>);
35+
static_assert(!is_constructible_v<move_only_function<const int&() const>, int (*)()>);
36+
37+
static_assert(!is_constructible_v<move_only_function<const int&() &>, LvalueTempFunctor>);
38+
static_assert(!is_constructible_v<move_only_function<const int&() const&>, LvalueTempFunctor>);
39+
static_assert(is_constructible_v<move_only_function<const int&() &&>, LvalueTempFunctor>);
40+
static_assert(is_constructible_v<move_only_function<const int&() const&&>, LvalueTempFunctor>);
41+
42+
#ifdef __cpp_noexcept_function_type
43+
static_assert(is_nothrow_invocable_r_v<const int&, int& (*) () noexcept>);
44+
static_assert(!is_nothrow_invocable_r_v<const int&, short& (*) () noexcept>);
45+
static_assert(!is_nothrow_invocable_r_v<const int&, int (*)() noexcept>);
46+
static_assert(!is_nothrow_invocable_r_v<int&&, int (*)() noexcept>);
47+
static_assert(is_nothrow_invocable_r_v<int, int (*)() noexcept>);
48+
static_assert(is_nothrow_invocable_r_v<const int&, LvalueTempFunctor>);
49+
static_assert(!is_nothrow_invocable_r_v<const int&, LvalueTempFunctor&>);
50+
51+
static_assert(is_constructible_v<move_only_function<const int&() noexcept>, int& (*) () noexcept>);
52+
static_assert(!is_constructible_v<move_only_function<const int&() noexcept>, short& (*) () noexcept>);
53+
static_assert(!is_constructible_v<move_only_function<const int&() noexcept>, int (*)() noexcept>);
54+
55+
static_assert(is_constructible_v<move_only_function<const int&() const noexcept>, int& (*) () noexcept>);
56+
static_assert(!is_constructible_v<move_only_function<const int&() const noexcept>, short& (*) () noexcept>);
57+
static_assert(!is_constructible_v<move_only_function<const int&() const noexcept>, int (*)() noexcept>);
58+
59+
static_assert(!is_constructible_v<move_only_function<const int&() & noexcept>, LvalueTempFunctor>);
60+
static_assert(!is_constructible_v<move_only_function<const int&() const & noexcept>, LvalueTempFunctor>);
61+
static_assert(is_constructible_v<move_only_function<const int&() && noexcept>, LvalueTempFunctor>);
62+
static_assert(is_constructible_v<move_only_function<const int&() const && noexcept>, LvalueTempFunctor>);
63+
#endif // defined(__cpp_noexcept_function_type)
64+
#endif // ^^^ no workaround ^^^
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
RUNALL_INCLUDE ..\usual_latest_matrix.lst

0 commit comments

Comments
 (0)