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
implies(bool p,bool q)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
sink(Args &&...)67 template <class ...Args> static void sink(Args&&...) {}
68
69 template <class ...TestTypes>
70 struct DoTestsMetafunction {
DoTestsMetafunctionDoTestsMetafunction71 DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); }
72 };
73
74 struct TrivialMoveNonTrivialCopy {
75 TrivialMoveNonTrivialCopy() = default;
TrivialMoveNonTrivialCopyTrivialMoveNonTrivialCopy76 TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {}
77 TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default;
operator =TrivialMoveNonTrivialCopy78 TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; }
79 TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default;
80 };
81
82 struct TrivialCopyNonTrivialMove {
83 TrivialCopyNonTrivialMove() = default;
84 TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default;
TrivialCopyNonTrivialMoveTrivialCopyNonTrivialMove85 TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {}
86 TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default;
operator =TrivialCopyNonTrivialMove87 TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; }
88 };
89
main(int,char **)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