1 | //===----------------------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 |
10 | |
11 | // test forward_like |
12 | |
13 | #include <cassert> |
14 | #include <type_traits> |
15 | #include <utility> |
16 | |
17 | struct U {}; // class type so const-qualification is not stripped from a prvalue |
18 | using CU = const U; |
19 | using T = int; |
20 | using CT = const T; |
21 | |
22 | U u{}; |
23 | const U& cu = u; |
24 | |
25 | static_assert(std::is_same_v<decltype(std::forward_like<T>(U{})), U&&>); |
26 | static_assert(std::is_same_v<decltype(std::forward_like<T>(CU{})), CU&&>); |
27 | static_assert(std::is_same_v<decltype(std::forward_like<T>(u)), U&&>); |
28 | static_assert(std::is_same_v<decltype(std::forward_like<T>(cu)), CU&&>); |
29 | static_assert(std::is_same_v<decltype(std::forward_like<T>(std::move(u))), U&&>); |
30 | static_assert(std::is_same_v<decltype(std::forward_like<T>(std::move(cu))), CU&&>); |
31 | |
32 | static_assert(std::is_same_v<decltype(std::forward_like<CT>(U{})), CU&&>); |
33 | static_assert(std::is_same_v<decltype(std::forward_like<CT>(CU{})), CU&&>); |
34 | static_assert(std::is_same_v<decltype(std::forward_like<CT>(u)), CU&&>); |
35 | static_assert(std::is_same_v<decltype(std::forward_like<CT>(cu)), CU&&>); |
36 | static_assert(std::is_same_v<decltype(std::forward_like<CT>(std::move(u))), CU&&>); |
37 | static_assert(std::is_same_v<decltype(std::forward_like<CT>(std::move(cu))), CU&&>); |
38 | |
39 | static_assert(std::is_same_v<decltype(std::forward_like<T&>(U{})), U&>); |
40 | static_assert(std::is_same_v<decltype(std::forward_like<T&>(CU{})), CU&>); |
41 | static_assert(std::is_same_v<decltype(std::forward_like<T&>(u)), U&>); |
42 | static_assert(std::is_same_v<decltype(std::forward_like<T&>(cu)), CU&>); |
43 | static_assert(std::is_same_v<decltype(std::forward_like<T&>(std::move(u))), U&>); |
44 | static_assert(std::is_same_v<decltype(std::forward_like<T&>(std::move(cu))), CU&>); |
45 | |
46 | static_assert(std::is_same_v<decltype(std::forward_like<CT&>(U{})), CU&>); |
47 | static_assert(std::is_same_v<decltype(std::forward_like<CT&>(CU{})), CU&>); |
48 | static_assert(std::is_same_v<decltype(std::forward_like<CT&>(u)), CU&>); |
49 | static_assert(std::is_same_v<decltype(std::forward_like<CT&>(cu)), CU&>); |
50 | static_assert(std::is_same_v<decltype(std::forward_like<CT&>(std::move(u))), CU&>); |
51 | static_assert(std::is_same_v<decltype(std::forward_like<CT&>(std::move(cu))), CU&>); |
52 | |
53 | static_assert(std::is_same_v<decltype(std::forward_like<T&&>(U{})), U&&>); |
54 | static_assert(std::is_same_v<decltype(std::forward_like<T&&>(CU{})), CU&&>); |
55 | static_assert(std::is_same_v<decltype(std::forward_like<T&&>(u)), U&&>); |
56 | static_assert(std::is_same_v<decltype(std::forward_like<T&&>(cu)), CU&&>); |
57 | static_assert(std::is_same_v<decltype(std::forward_like<T&&>(std::move(u))), U&&>); |
58 | static_assert(std::is_same_v<decltype(std::forward_like<T&&>(std::move(cu))), CU&&>); |
59 | |
60 | static_assert(std::is_same_v<decltype(std::forward_like<CT&&>(U{})), CU&&>); |
61 | static_assert(std::is_same_v<decltype(std::forward_like<CT&&>(CU{})), CU&&>); |
62 | static_assert(std::is_same_v<decltype(std::forward_like<CT&&>(u)), CU&&>); |
63 | static_assert(std::is_same_v<decltype(std::forward_like<CT&&>(cu)), CU&&>); |
64 | static_assert(std::is_same_v<decltype(std::forward_like<CT&&>(std::move(u))), CU&&>); |
65 | static_assert(std::is_same_v<decltype(std::forward_like<CT&&>(std::move(cu))), CU&&>); |
66 | |
67 | static_assert(noexcept(std::forward_like<T>(u))); |
68 | |
69 | static_assert(std::is_same_v<decltype(std::forward_like<U&>(u)), U&>); |
70 | static_assert(std::is_same_v<decltype(std::forward_like<CU&>(cu)), CU&>); |
71 | static_assert(std::is_same_v<decltype(std::forward_like<U&&>(std::move(u))), U&&>); |
72 | static_assert(std::is_same_v<decltype(std::forward_like<CU&&>(std::move(cu))), CU&&>); |
73 | |
74 | struct NoCtorCopyMove { |
75 | NoCtorCopyMove() = delete; |
76 | NoCtorCopyMove(const NoCtorCopyMove&) = delete; |
77 | NoCtorCopyMove(NoCtorCopyMove&&) = delete; |
78 | }; |
79 | |
80 | static_assert(std::is_same_v<decltype(std::forward_like<CT&&>(std::declval<NoCtorCopyMove>())), const NoCtorCopyMove&&>); |
81 | static_assert(std::is_same_v<decltype(std::forward_like<CT&>(std::declval<NoCtorCopyMove>())), const NoCtorCopyMove&>); |
82 | static_assert(std::is_same_v<decltype(std::forward_like<T&&>(std::declval<NoCtorCopyMove>())), NoCtorCopyMove&&>); |
83 | static_assert(std::is_same_v<decltype(std::forward_like<T&>(std::declval<NoCtorCopyMove>())), NoCtorCopyMove&>); |
84 | |
85 | static_assert(noexcept(std::forward_like<T>(std::declval<NoCtorCopyMove>()))); |
86 | |
87 | constexpr bool test() { |
88 | { |
89 | int val = 1729; |
90 | auto&& result = std::forward_like<const double&>(val); |
91 | static_assert(std::is_same_v<decltype(result), const int&>); |
92 | assert(&result == &val); |
93 | } |
94 | { |
95 | int val = 1729; |
96 | auto&& result = std::forward_like<double&>(val); |
97 | static_assert(std::is_same_v<decltype(result), int&>); |
98 | assert(&result == &val); |
99 | } |
100 | { |
101 | int val = 1729; |
102 | auto&& result = std::forward_like<const double&&>(val); |
103 | static_assert(std::is_same_v<decltype(result), const int&&>); |
104 | assert(&result == &val); |
105 | } |
106 | { |
107 | int val = 1729; |
108 | auto&& result = std::forward_like<double&&>(val); |
109 | static_assert(std::is_same_v<decltype(result), int&&>); |
110 | assert(&result == &val); |
111 | } |
112 | return true; |
113 | } |
114 | |
115 | int main(int, char**) { |
116 | test(); |
117 | static_assert(test()); |
118 | |
119 | return 0; |
120 | } |
121 | |