xref: /llvm-project/libcxx/test/std/utilities/expected/expected.expected/assign/emplace.pass.cpp (revision 5f2da9c80db99c302de9938d5785e43a3d71fa6f)
1 //===----------------------------------------------------------------------===//
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 
8 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
9 
10 // template<class... Args>
11 //   constexpr T& emplace(Args&&... args) noexcept;
12 // Constraints: is_nothrow_constructible_v<T, Args...> is true.
13 //
14 // Effects: Equivalent to:
15 // if (has_value()) {
16 //   destroy_at(addressof(val));
17 // } else {
18 //   destroy_at(addressof(unex));
19 //   has_val = true;
20 // }
21 // return *construct_at(addressof(val), std::forward<Args>(args)...);
22 
23 #include <cassert>
24 #include <concepts>
25 #include <expected>
26 #include <type_traits>
27 #include <utility>
28 
29 #include "../../types.h"
30 #include "test_macros.h"
31 
32 template <class T, class... Args>
33 concept CanEmplace = requires(T t, Args&&... args) { t.emplace(std::forward<Args>(args)...); };
34 
35 static_assert(CanEmplace<std::expected<int, int>, int>);
36 
37 template <bool Noexcept>
38 struct CtorFromInt {
39   CtorFromInt(int) noexcept(Noexcept);
40   CtorFromInt(int, int) noexcept(Noexcept);
41 };
42 
43 static_assert(CanEmplace<std::expected<CtorFromInt<true>, int>, int>);
44 static_assert(CanEmplace<std::expected<CtorFromInt<true>, int>, int, int>);
45 static_assert(!CanEmplace<std::expected<CtorFromInt<false>, int>, int>);
46 static_assert(!CanEmplace<std::expected<CtorFromInt<false>, int>, int, int>);
47 
48 constexpr bool test() {
49   // has_value
50   {
51     BothNoexcept::state oldState{};
52     BothNoexcept::state newState{};
53     std::expected<BothNoexcept, int> e(std::in_place, oldState, 5);
54     decltype(auto) x = e.emplace(newState, 10);
55     static_assert(std::same_as<decltype(x), BothNoexcept&>);
56     assert(&x == &(*e));
57 
58     assert(oldState.dtorCalled);
59     assert(e.has_value());
60     assert(e.value().data_ == 10);
61   }
62 
63   // !has_value
64   {
65     BothMayThrow::state oldState{};
66     std::expected<int, BothMayThrow> e(std::unexpect, oldState, 5);
67     decltype(auto) x = e.emplace(10);
68     static_assert(std::same_as<decltype(x), int&>);
69     assert(&x == &(*e));
70 
71     assert(oldState.dtorCalled);
72     assert(e.has_value());
73     assert(e.value() == 10);
74   }
75 
76   return true;
77 }
78 
79 int main(int, char**) {
80   test();
81   static_assert(test());
82   return 0;
83 }
84