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// <optional>
12
13// template<class F> constexpr auto transform(F&&) &;
14// template<class F> constexpr auto transform(F&&) &&;
15// template<class F> constexpr auto transform(F&&) const&;
16// template<class F> constexpr auto transform(F&&) const&&;
17
18#include "test_macros.h"
19#include <cassert>
20#include <optional>
21#include <type_traits>
22
23struct LVal {
24 constexpr int operator()(int&) { return 1; }
25 int operator()(const int&) = delete;
26 int operator()(int&&) = delete;
27 int operator()(const int&&) = delete;
28};
29
30struct CLVal {
31 int operator()(int&) = delete;
32 constexpr int operator()(const int&) { return 1; }
33 int operator()(int&&) = delete;
34 int operator()(const int&&) = delete;
35};
36
37struct RVal {
38 int operator()(int&) = delete;
39 int operator()(const int&) = delete;
40 constexpr int operator()(int&&) { return 1; }
41 int operator()(const int&&) = delete;
42};
43
44struct CRVal {
45 int operator()(int&) = delete;
46 int operator()(const int&) = delete;
47 int operator()(int&&) = delete;
48 constexpr int operator()(const int&&) { return 1; }
49};
50
51struct RefQual {
52 constexpr int operator()(int) & { return 1; }
53 int operator()(int) const& = delete;
54 int operator()(int) && = delete;
55 int operator()(int) const&& = delete;
56};
57
58struct CRefQual {
59 int operator()(int) & = delete;
60 constexpr int operator()(int) const& { return 1; }
61 int operator()(int) && = delete;
62 int operator()(int) const&& = delete;
63};
64
65struct RVRefQual {
66 int operator()(int) & = delete;
67 int operator()(int) const& = delete;
68 constexpr int operator()(int) && { return 1; }
69 int operator()(int) const&& = delete;
70};
71
72struct RVCRefQual {
73 int operator()(int) & = delete;
74 int operator()(int) const& = delete;
75 int operator()(int) && = delete;
76 constexpr int operator()(int) const&& { return 1; }
77};
78
79struct NoCopy {
80 NoCopy() = default;
81 NoCopy(const NoCopy&) { assert(false); }
82 int operator()(const NoCopy&&) { return 1; }
83};
84
85struct NoMove {
86 NoMove() = default;
87 NoMove(NoMove&&) = delete;
88 NoMove operator()(const NoCopy&&) { return NoMove{}; }
89};
90
91constexpr void test_val_types() {
92 // Test & overload
93 {
94 // Without & qualifier on F's operator()
95 {
96 std::optional<int> i{0};
97 assert(i.transform(LVal{}) == 1);
98 ASSERT_SAME_TYPE(decltype(i.transform(LVal{})), std::optional<int>);
99 }
100
101 //With & qualifier on F's operator()
102 {
103 std::optional<int> i{0};
104 RefQual l{};
105 assert(i.transform(l) == 1);
106 ASSERT_SAME_TYPE(decltype(i.transform(l)), std::optional<int>);
107 }
108 }
109
110 // Test const& overload
111 {
112 // Without & qualifier on F's operator()
113 {
114 const std::optional<int> i{0};
115 assert(i.transform(CLVal{}) == 1);
116 ASSERT_SAME_TYPE(decltype(i.transform(CLVal{})), std::optional<int>);
117 }
118
119 //With & qualifier on F's operator()
120 {
121 const std::optional<int> i{0};
122 const CRefQual l{};
123 assert(i.transform(l) == 1);
124 ASSERT_SAME_TYPE(decltype(i.transform(l)), std::optional<int>);
125 }
126 }
127
128 // Test && overload
129 {
130 // Without & qualifier on F's operator()
131 {
132 std::optional<int> i{0};
133 assert(std::move(i).transform(RVal{}) == 1);
134 ASSERT_SAME_TYPE(decltype(std::move(i).transform(RVal{})), std::optional<int>);
135 }
136
137 //With & qualifier on F's operator()
138 {
139 std::optional<int> i{0};
140 assert(i.transform(RVRefQual{}) == 1);
141 ASSERT_SAME_TYPE(decltype(i.transform(RVRefQual{})), std::optional<int>);
142 }
143 }
144
145 // Test const&& overload
146 {
147 // Without & qualifier on F's operator()
148 {
149 const std::optional<int> i{0};
150 assert(std::move(i).transform(CRVal{}) == 1);
151 ASSERT_SAME_TYPE(decltype(std::move(i).transform(CRVal{})), std::optional<int>);
152 }
153
154 //With & qualifier on F's operator()
155 {
156 const std::optional<int> i{0};
157 const RVCRefQual l{};
158 assert(i.transform(std::move(l)) == 1);
159 ASSERT_SAME_TYPE(decltype(i.transform(std::move(l))), std::optional<int>);
160 }
161 }
162}
163
164struct NonConst {
165 int non_const() { return 1; }
166};
167
168// check that the lambda body is not instantiated during overload resolution
169constexpr void test_sfinae() {
170 std::optional<NonConst> opt{};
171 auto l = [](auto&& x) { return x.non_const(); };
172 opt.transform(l);
173 std::move(opt).transform(l);
174}
175
176constexpr bool test() {
177 test_sfinae();
178 test_val_types();
179 std::optional<int> opt;
180 const auto& copt = opt;
181
182 const auto never_called = [](int) {
183 assert(false);
184 return 0;
185 };
186
187 opt.transform(never_called);
188 std::move(opt).transform(never_called);
189 copt.transform(never_called);
190 std::move(copt).transform(never_called);
191
192 std::optional<NoCopy> nc;
193 const auto& cnc = nc;
194 std::move(nc).transform(NoCopy{});
195 std::move(cnc).transform(NoCopy{});
196
197 std::move(nc).transform(NoMove{});
198 std::move(cnc).transform(NoMove{});
199
200 return true;
201}
202
203int main(int, char**) {
204 test();
205 static_assert(test());
206 return 0;
207}
208

source code of libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp