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 |
10 | |
11 | // <optional> |
12 | |
13 | // The following special member functions should propagate the triviality of |
14 | // the element held in the optional (see P0602R4): |
15 | // |
16 | // constexpr optional(const optional& rhs); |
17 | // constexpr optional(optional&& rhs) noexcept(see below); |
18 | // constexpr optional<T>& operator=(const optional& rhs); |
19 | // constexpr optional<T>& operator=(optional&& rhs) noexcept(see below); |
20 | |
21 | |
22 | #include <optional> |
23 | #include <type_traits> |
24 | |
25 | #include "archetypes.h" |
26 | |
27 | #include "test_macros.h" |
28 | |
29 | |
30 | constexpr bool implies(bool p, bool q) { |
31 | return !p || q; |
32 | } |
33 | |
34 | template <class T> |
35 | struct SpecialMemberTest { |
36 | using O = std::optional<T>; |
37 | |
38 | static_assert(implies(std::is_trivially_copy_constructible_v<T>, |
39 | std::is_trivially_copy_constructible_v<O>), |
40 | "optional<T> is trivially copy constructible if T is trivially copy constructible." ); |
41 | |
42 | static_assert(implies(std::is_trivially_move_constructible_v<T>, |
43 | std::is_trivially_move_constructible_v<O>), |
44 | "optional<T> is trivially move constructible if T is trivially move constructible" ); |
45 | |
46 | static_assert(implies(std::is_trivially_copy_constructible_v<T> && |
47 | std::is_trivially_copy_assignable_v<T> && |
48 | std::is_trivially_destructible_v<T>, |
49 | |
50 | std::is_trivially_copy_assignable_v<O>), |
51 | "optional<T> is trivially copy assignable if T is " |
52 | "trivially copy constructible, " |
53 | "trivially copy assignable, and " |
54 | "trivially destructible" ); |
55 | |
56 | static_assert(implies(std::is_trivially_move_constructible_v<T> && |
57 | std::is_trivially_move_assignable_v<T> && |
58 | std::is_trivially_destructible_v<T>, |
59 | |
60 | std::is_trivially_move_assignable_v<O>), |
61 | "optional<T> is trivially move assignable if T is " |
62 | "trivially move constructible, " |
63 | "trivially move assignable, and" |
64 | "trivially destructible." ); |
65 | }; |
66 | |
67 | template <class ...Args> static void sink(Args&&...) {} |
68 | |
69 | template <class ...TestTypes> |
70 | struct DoTestsMetafunction { |
71 | DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); } |
72 | }; |
73 | |
74 | struct TrivialMoveNonTrivialCopy { |
75 | TrivialMoveNonTrivialCopy() = default; |
76 | TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {} |
77 | TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default; |
78 | TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; } |
79 | TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default; |
80 | }; |
81 | |
82 | struct TrivialCopyNonTrivialMove { |
83 | TrivialCopyNonTrivialMove() = default; |
84 | TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default; |
85 | TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {} |
86 | TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default; |
87 | TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; } |
88 | }; |
89 | |
90 | int main(int, char**) { |
91 | sink( |
92 | ImplicitTypes::ApplyTypes<DoTestsMetafunction>{}, |
93 | ExplicitTypes::ApplyTypes<DoTestsMetafunction>{}, |
94 | NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{}, |
95 | NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{}, |
96 | DoTestsMetafunction<TrivialMoveNonTrivialCopy, TrivialCopyNonTrivialMove>{} |
97 | ); |
98 | return 0; |
99 | } |
100 | |