117cfc57dSNikolas Klauser //===----------------------------------------------------------------------===//
217cfc57dSNikolas Klauser //
317cfc57dSNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
417cfc57dSNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
517cfc57dSNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
617cfc57dSNikolas Klauser //
717cfc57dSNikolas Klauser //===----------------------------------------------------------------------===//
817cfc57dSNikolas Klauser
917cfc57dSNikolas Klauser // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10*fd4cc870SLouis Dionne
11*fd4cc870SLouis Dionne // Throwing bad_optional_access is supported starting in macosx10.13
12*fd4cc870SLouis Dionne // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12}} && !no-exceptions
13*fd4cc870SLouis Dionne
1417cfc57dSNikolas Klauser // <optional>
1517cfc57dSNikolas Klauser
1617cfc57dSNikolas Klauser // template<class F> constexpr auto transform(F&&) &;
1717cfc57dSNikolas Klauser // template<class F> constexpr auto transform(F&&) &&;
1817cfc57dSNikolas Klauser // template<class F> constexpr auto transform(F&&) const&;
1917cfc57dSNikolas Klauser // template<class F> constexpr auto transform(F&&) const&&;
2017cfc57dSNikolas Klauser
2117cfc57dSNikolas Klauser #include "test_macros.h"
2217cfc57dSNikolas Klauser #include <cassert>
2317cfc57dSNikolas Klauser #include <optional>
2417cfc57dSNikolas Klauser #include <type_traits>
2517cfc57dSNikolas Klauser
2617cfc57dSNikolas Klauser struct LVal {
operator ()LVal2717cfc57dSNikolas Klauser constexpr int operator()(int&) { return 1; }
2817cfc57dSNikolas Klauser int operator()(const int&) = delete;
2917cfc57dSNikolas Klauser int operator()(int&&) = delete;
3017cfc57dSNikolas Klauser int operator()(const int&&) = delete;
3117cfc57dSNikolas Klauser };
3217cfc57dSNikolas Klauser
3317cfc57dSNikolas Klauser struct CLVal {
3417cfc57dSNikolas Klauser int operator()(int&) = delete;
operator ()CLVal3517cfc57dSNikolas Klauser constexpr int operator()(const int&) { return 1; }
3617cfc57dSNikolas Klauser int operator()(int&&) = delete;
3717cfc57dSNikolas Klauser int operator()(const int&&) = delete;
3817cfc57dSNikolas Klauser };
3917cfc57dSNikolas Klauser
4017cfc57dSNikolas Klauser struct RVal {
4117cfc57dSNikolas Klauser int operator()(int&) = delete;
4217cfc57dSNikolas Klauser int operator()(const int&) = delete;
operator ()RVal4317cfc57dSNikolas Klauser constexpr int operator()(int&&) { return 1; }
4417cfc57dSNikolas Klauser int operator()(const int&&) = delete;
4517cfc57dSNikolas Klauser };
4617cfc57dSNikolas Klauser
4717cfc57dSNikolas Klauser struct CRVal {
4817cfc57dSNikolas Klauser int operator()(int&) = delete;
4917cfc57dSNikolas Klauser int operator()(const int&) = delete;
5017cfc57dSNikolas Klauser int operator()(int&&) = delete;
operator ()CRVal5117cfc57dSNikolas Klauser constexpr int operator()(const int&&) { return 1; }
5217cfc57dSNikolas Klauser };
5317cfc57dSNikolas Klauser
5417cfc57dSNikolas Klauser struct RefQual {
operator ()RefQual5517cfc57dSNikolas Klauser constexpr int operator()(int) & { return 1; }
5617cfc57dSNikolas Klauser int operator()(int) const& = delete;
5717cfc57dSNikolas Klauser int operator()(int) && = delete;
5817cfc57dSNikolas Klauser int operator()(int) const&& = delete;
5917cfc57dSNikolas Klauser };
6017cfc57dSNikolas Klauser
6117cfc57dSNikolas Klauser struct CRefQual {
6217cfc57dSNikolas Klauser int operator()(int) & = delete;
operator ()CRefQual6317cfc57dSNikolas Klauser constexpr int operator()(int) const& { return 1; }
6417cfc57dSNikolas Klauser int operator()(int) && = delete;
6517cfc57dSNikolas Klauser int operator()(int) const&& = delete;
6617cfc57dSNikolas Klauser };
6717cfc57dSNikolas Klauser
6817cfc57dSNikolas Klauser struct RVRefQual {
6917cfc57dSNikolas Klauser int operator()(int) & = delete;
7017cfc57dSNikolas Klauser int operator()(int) const& = delete;
operator ()RVRefQual7117cfc57dSNikolas Klauser constexpr int operator()(int) && { return 1; }
7217cfc57dSNikolas Klauser int operator()(int) const&& = delete;
7317cfc57dSNikolas Klauser };
7417cfc57dSNikolas Klauser
7517cfc57dSNikolas Klauser struct RVCRefQual {
7617cfc57dSNikolas Klauser int operator()(int) & = delete;
7717cfc57dSNikolas Klauser int operator()(int) const& = delete;
7817cfc57dSNikolas Klauser int operator()(int) && = delete;
operator ()RVCRefQual7917cfc57dSNikolas Klauser constexpr int operator()(int) const&& { return 1; }
8017cfc57dSNikolas Klauser };
8117cfc57dSNikolas Klauser
8217cfc57dSNikolas Klauser struct NoCopy {
8317cfc57dSNikolas Klauser NoCopy() = default;
NoCopyNoCopy8417cfc57dSNikolas Klauser NoCopy(const NoCopy&) { assert(false); }
operator ()NoCopy8517cfc57dSNikolas Klauser int operator()(const NoCopy&&) { return 1; }
8617cfc57dSNikolas Klauser };
8717cfc57dSNikolas Klauser
8817cfc57dSNikolas Klauser struct NoMove {
8917cfc57dSNikolas Klauser NoMove() = default;
9017cfc57dSNikolas Klauser NoMove(NoMove&&) = delete;
operator ()NoMove9117cfc57dSNikolas Klauser NoMove operator()(const NoCopy&&) { return NoMove{}; }
9217cfc57dSNikolas Klauser };
9317cfc57dSNikolas Klauser
test_val_types()9417cfc57dSNikolas Klauser constexpr void test_val_types() {
9517cfc57dSNikolas Klauser // Test & overload
9617cfc57dSNikolas Klauser {
9717cfc57dSNikolas Klauser // Without & qualifier on F's operator()
9817cfc57dSNikolas Klauser {
9917cfc57dSNikolas Klauser std::optional<int> i{0};
10017cfc57dSNikolas Klauser assert(i.transform(LVal{}) == 1);
10117cfc57dSNikolas Klauser ASSERT_SAME_TYPE(decltype(i.transform(LVal{})), std::optional<int>);
10217cfc57dSNikolas Klauser }
10317cfc57dSNikolas Klauser
10417cfc57dSNikolas Klauser //With & qualifier on F's operator()
10517cfc57dSNikolas Klauser {
10617cfc57dSNikolas Klauser std::optional<int> i{0};
10717cfc57dSNikolas Klauser RefQual l{};
10817cfc57dSNikolas Klauser assert(i.transform(l) == 1);
10917cfc57dSNikolas Klauser ASSERT_SAME_TYPE(decltype(i.transform(l)), std::optional<int>);
11017cfc57dSNikolas Klauser }
11117cfc57dSNikolas Klauser }
11217cfc57dSNikolas Klauser
11317cfc57dSNikolas Klauser // Test const& overload
11417cfc57dSNikolas Klauser {
11517cfc57dSNikolas Klauser // Without & qualifier on F's operator()
11617cfc57dSNikolas Klauser {
11717cfc57dSNikolas Klauser const std::optional<int> i{0};
11817cfc57dSNikolas Klauser assert(i.transform(CLVal{}) == 1);
11917cfc57dSNikolas Klauser ASSERT_SAME_TYPE(decltype(i.transform(CLVal{})), std::optional<int>);
12017cfc57dSNikolas Klauser }
12117cfc57dSNikolas Klauser
12217cfc57dSNikolas Klauser //With & qualifier on F's operator()
12317cfc57dSNikolas Klauser {
12417cfc57dSNikolas Klauser const std::optional<int> i{0};
12517cfc57dSNikolas Klauser const CRefQual l{};
12617cfc57dSNikolas Klauser assert(i.transform(l) == 1);
12717cfc57dSNikolas Klauser ASSERT_SAME_TYPE(decltype(i.transform(l)), std::optional<int>);
12817cfc57dSNikolas Klauser }
12917cfc57dSNikolas Klauser }
13017cfc57dSNikolas Klauser
13117cfc57dSNikolas Klauser // Test && overload
13217cfc57dSNikolas Klauser {
13317cfc57dSNikolas Klauser // Without & qualifier on F's operator()
13417cfc57dSNikolas Klauser {
13517cfc57dSNikolas Klauser std::optional<int> i{0};
13617cfc57dSNikolas Klauser assert(std::move(i).transform(RVal{}) == 1);
13717cfc57dSNikolas Klauser ASSERT_SAME_TYPE(decltype(std::move(i).transform(RVal{})), std::optional<int>);
13817cfc57dSNikolas Klauser }
13917cfc57dSNikolas Klauser
14017cfc57dSNikolas Klauser //With & qualifier on F's operator()
14117cfc57dSNikolas Klauser {
14217cfc57dSNikolas Klauser std::optional<int> i{0};
14317cfc57dSNikolas Klauser assert(i.transform(RVRefQual{}) == 1);
14417cfc57dSNikolas Klauser ASSERT_SAME_TYPE(decltype(i.transform(RVRefQual{})), std::optional<int>);
14517cfc57dSNikolas Klauser }
14617cfc57dSNikolas Klauser }
14717cfc57dSNikolas Klauser
14817cfc57dSNikolas Klauser // Test const&& overload
14917cfc57dSNikolas Klauser {
15017cfc57dSNikolas Klauser // Without & qualifier on F's operator()
15117cfc57dSNikolas Klauser {
15217cfc57dSNikolas Klauser const std::optional<int> i{0};
15317cfc57dSNikolas Klauser assert(std::move(i).transform(CRVal{}) == 1);
15417cfc57dSNikolas Klauser ASSERT_SAME_TYPE(decltype(std::move(i).transform(CRVal{})), std::optional<int>);
15517cfc57dSNikolas Klauser }
15617cfc57dSNikolas Klauser
15717cfc57dSNikolas Klauser //With & qualifier on F's operator()
15817cfc57dSNikolas Klauser {
15917cfc57dSNikolas Klauser const std::optional<int> i{0};
16017cfc57dSNikolas Klauser const RVCRefQual l{};
16117cfc57dSNikolas Klauser assert(i.transform(std::move(l)) == 1);
16217cfc57dSNikolas Klauser ASSERT_SAME_TYPE(decltype(i.transform(std::move(l))), std::optional<int>);
16317cfc57dSNikolas Klauser }
16417cfc57dSNikolas Klauser }
16517cfc57dSNikolas Klauser }
16617cfc57dSNikolas Klauser
16717cfc57dSNikolas Klauser struct NonConst {
non_constNonConst16817cfc57dSNikolas Klauser int non_const() { return 1; }
16917cfc57dSNikolas Klauser };
17017cfc57dSNikolas Klauser
17117cfc57dSNikolas Klauser // check that the lambda body is not instantiated during overload resolution
test_sfinae()17217cfc57dSNikolas Klauser constexpr void test_sfinae() {
17317cfc57dSNikolas Klauser std::optional<NonConst> opt{};
17417cfc57dSNikolas Klauser auto l = [](auto&& x) { return x.non_const(); };
17517cfc57dSNikolas Klauser opt.transform(l);
17617cfc57dSNikolas Klauser std::move(opt).transform(l);
17717cfc57dSNikolas Klauser }
17817cfc57dSNikolas Klauser
test()17917cfc57dSNikolas Klauser constexpr bool test() {
18017cfc57dSNikolas Klauser test_sfinae();
18117cfc57dSNikolas Klauser test_val_types();
18217cfc57dSNikolas Klauser std::optional<int> opt;
18317cfc57dSNikolas Klauser const auto& copt = opt;
18417cfc57dSNikolas Klauser
18517cfc57dSNikolas Klauser const auto never_called = [](int) {
18617cfc57dSNikolas Klauser assert(false);
18717cfc57dSNikolas Klauser return 0;
18817cfc57dSNikolas Klauser };
18917cfc57dSNikolas Klauser
19017cfc57dSNikolas Klauser opt.transform(never_called);
19117cfc57dSNikolas Klauser std::move(opt).transform(never_called);
19217cfc57dSNikolas Klauser copt.transform(never_called);
19317cfc57dSNikolas Klauser std::move(copt).transform(never_called);
19417cfc57dSNikolas Klauser
19517cfc57dSNikolas Klauser std::optional<NoCopy> nc;
19617cfc57dSNikolas Klauser const auto& cnc = nc;
19717cfc57dSNikolas Klauser std::move(nc).transform(NoCopy{});
19817cfc57dSNikolas Klauser std::move(cnc).transform(NoCopy{});
19917cfc57dSNikolas Klauser
20017cfc57dSNikolas Klauser std::move(nc).transform(NoMove{});
20117cfc57dSNikolas Klauser std::move(cnc).transform(NoMove{});
20217cfc57dSNikolas Klauser
20317cfc57dSNikolas Klauser return true;
20417cfc57dSNikolas Klauser }
20517cfc57dSNikolas Klauser
main(int,char **)20617cfc57dSNikolas Klauser int main(int, char**) {
20717cfc57dSNikolas Klauser test();
20817cfc57dSNikolas Klauser static_assert(test());
209c31cf74cSLouis Dionne return 0;
21017cfc57dSNikolas Klauser }
211