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
test()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
main(int,char **)115 int main(int, char**) {
116 test();
117 static_assert(test());
118
119 return 0;
120 }
121