313 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++17, c++2010 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 <concepts>21#include <optional>22#include <type_traits>23#include <utility>24 25struct LVal {26 constexpr int operator()(int&) { return 1; }27 int operator()(const int&) = delete;28 int operator()(int&&) = delete;29 int operator()(const int&&) = delete;30};31 32struct CLVal {33 int operator()(int&) = delete;34 constexpr int operator()(const int&) { return 1; }35 int operator()(int&&) = delete;36 int operator()(const int&&) = delete;37};38 39struct RVal {40 int operator()(int&) = delete;41 int operator()(const int&) = delete;42 constexpr int operator()(int&&) { return 1; }43 int operator()(const int&&) = delete;44};45 46struct CRVal {47 int operator()(int&) = delete;48 int operator()(const int&) = delete;49 int operator()(int&&) = delete;50 constexpr int operator()(const int&&) { return 1; }51};52 53struct RefQual {54 constexpr int operator()(int) & { return 1; }55 int operator()(int) const& = delete;56 int operator()(int) && = delete;57 int operator()(int) const&& = delete;58};59 60struct CRefQual {61 int operator()(int) & = delete;62 constexpr int operator()(int) const& { return 1; }63 int operator()(int) && = delete;64 int operator()(int) const&& = delete;65};66 67struct RVRefQual {68 int operator()(int) & = delete;69 int operator()(int) const& = delete;70 constexpr int operator()(int) && { return 1; }71 int operator()(int) const&& = delete;72};73 74struct RVCRefQual {75 int operator()(int) & = delete;76 int operator()(int) const& = delete;77 int operator()(int) && = delete;78 constexpr int operator()(int) const&& { return 1; }79};80 81struct NoCopy {82 NoCopy() = default;83 NoCopy(const NoCopy&) { assert(false); }84 int operator()(const NoCopy&&) { return 1; }85};86 87struct NoMove {88 NoMove() = default;89 NoMove(NoMove&&) = delete;90 NoMove operator()(const NoCopy&&) { return NoMove{}; }91};92 93constexpr void test_val_types() {94 // Test & overload95 {96 // Without & qualifier on F's operator()97 {98 std::optional<int> i{0};99 assert(i.transform(LVal{}) == 1);100 ASSERT_SAME_TYPE(decltype(i.transform(LVal{})), std::optional<int>);101 }102 103 //With & qualifier on F's operator()104 {105 std::optional<int> i{0};106 RefQual l{};107 assert(i.transform(l) == 1);108 ASSERT_SAME_TYPE(decltype(i.transform(l)), std::optional<int>);109 }110 }111 112 // Test const& overload113 {114 // Without & qualifier on F's operator()115 {116 const std::optional<int> i{0};117 assert(i.transform(CLVal{}) == 1);118 ASSERT_SAME_TYPE(decltype(i.transform(CLVal{})), std::optional<int>);119 }120 121 //With & qualifier on F's operator()122 {123 const std::optional<int> i{0};124 const CRefQual l{};125 assert(i.transform(l) == 1);126 ASSERT_SAME_TYPE(decltype(i.transform(l)), std::optional<int>);127 }128 }129 130 // Test && overload131 {132 // Without & qualifier on F's operator()133 {134 std::optional<int> i{0};135 assert(std::move(i).transform(RVal{}) == 1);136 ASSERT_SAME_TYPE(decltype(std::move(i).transform(RVal{})), std::optional<int>);137 }138 139 //With & qualifier on F's operator()140 {141 std::optional<int> i{0};142 assert(i.transform(RVRefQual{}) == 1);143 ASSERT_SAME_TYPE(decltype(i.transform(RVRefQual{})), std::optional<int>);144 }145 }146 147 // Test const&& overload148 {149 // Without & qualifier on F's operator()150 {151 const std::optional<int> i{0};152 assert(std::move(i).transform(CRVal{}) == 1);153 ASSERT_SAME_TYPE(decltype(std::move(i).transform(CRVal{})), std::optional<int>);154 }155 156 //With & qualifier on F's operator()157 {158 const std::optional<int> i{0};159 const RVCRefQual l{};160 assert(i.transform(std::move(l)) == 1);161 ASSERT_SAME_TYPE(decltype(i.transform(std::move(l))), std::optional<int>);162 }163 }164}165 166struct NonConst {167 int non_const() { return 1; }168};169 170// check that the lambda body is not instantiated during overload resolution171constexpr void test_sfinae() {172 std::optional<NonConst> opt{};173 auto l = [](auto&& x) { return x.non_const(); };174 opt.transform(l);175 std::move(opt).transform(l);176}177 178constexpr bool test() {179 test_sfinae();180 test_val_types();181 std::optional<int> opt;182 const auto& copt = opt;183 184 const auto never_called = [](int) {185 assert(false);186 return 0;187 };188 189 opt.transform(never_called);190 std::move(opt).transform(never_called);191 copt.transform(never_called);192 std::move(copt).transform(never_called);193 194 std::optional<NoCopy> nc;195 const auto& cnc = nc;196 std::move(nc).transform(NoCopy{});197 std::move(cnc).transform(NoCopy{});198 199 std::move(nc).transform(NoMove{});200 std::move(cnc).transform(NoMove{});201 202 return true;203}204 205#if TEST_STD_VER >= 26206constexpr bool test_ref() {207 {208 std::optional<int&> opt1;209 std::same_as<std::optional<int>> decltype(auto) opt1r = opt1.transform([](int i) { return i + 2; });210 assert(!opt1);211 assert(!opt1r);212 }213 214 {215 int i = 42;216 std::optional<int&> opt{i};217 std::same_as<std::optional<int>> decltype(auto) o2 = opt.transform([](int j) { return j + 2; });218 219 assert(*o2 == 44);220 }221 // Test & overload222 {223 // Without & qualifier on F's operator()224 {225 int i = 42;226 std::optional<int&> opt{i};227 std::same_as<std::optional<int>> decltype(auto) o3 = opt.transform(LVal{});228 229 assert(*o3 == 1);230 }231 232 //With & qualifier on F's operator()233 {234 int i = 42;235 std::optional<int&> opt{i};236 RefQual l{};237 std::same_as<std::optional<int>> decltype(auto) o3 = opt.transform(l);238 239 assert(*o3 == 1);240 }241 }242 // const& overload243 {244 // Without & qualifier on F's operator()245 {246 int i = 42;247 std::optional<const int&> opt{i};248 std::same_as<std::optional<int>> decltype(auto) o3 = std::as_const(opt).transform(CLVal{});249 250 assert(*o3 == 1);251 }252 253 //With & qualifier on F's operator()254 {255 int i = 42;256 const std::optional<int&> opt{i};257 const CRefQual l{};258 std::same_as<std::optional<int>> decltype(auto) o3 = opt.transform(l);259 260 assert(*o3 == 1);261 }262 }263 264 // Test && overload265 {266 // Without & qualifier on F's operator()267 {268 int i = 42;269 std::optional<int> opt{i};270 std::same_as<std::optional<int>> decltype(auto) o3 = std::move(opt).transform(RVal{});271 272 assert(*o3 == 1);273 }274 275 //With & qualifier on F's operator()276 {277 int i = 42;278 std::optional<int&> opt{i};279 std::same_as<std::optional<int>> decltype(auto) o3 = std::move(opt).transform(RVRefQual{});280 assert(*o3 == 1);281 }282 }283 284 // const&& overload285 {286 //With & qualifier on F's operator()287 {288 int i = 42;289 std::optional<int&> opt{i};290 const RVCRefQual rvc{};291 std::same_as<std::optional<int>> decltype(auto) o3 = opt.transform(std::move(rvc));292 assert(*o3 == 1);293 }294 }295 {296 std::optional<int&> o6 = std::nullopt;297 auto o6r = o6.transform([](int) { return 42; });298 assert(!o6r);299 }300 return true;301}302#endif303 304int main(int, char**) {305 test();306 static_assert(test());307#if TEST_STD_VER >= 26308 test_ref();309 static_assert(test_ref());310#endif311 return 0;312}313