1 //===----------------------------------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
11
12 // <optional>
13
14 // The following special member functions should propagate the triviality of
15 // the element held in the optional (see P0602R4):
16 //
17 // constexpr optional(const optional& rhs);
18 // constexpr optional(optional&& rhs) noexcept(see below);
19 // constexpr optional<T>& operator=(const optional& rhs);
20 // constexpr optional<T>& operator=(optional&& rhs) noexcept(see below);
21
22
23 #include <optional>
24 #include <type_traits>
25
26 #include "archetypes.hpp"
27
28
implies(bool p,bool q)29 constexpr bool implies(bool p, bool q) {
30 return !p || q;
31 }
32
33 template <class T>
34 struct SpecialMemberTest {
35 using O = std::optional<T>;
36
37 static_assert(implies(std::is_trivially_copy_constructible_v<T>,
38 std::is_trivially_copy_constructible_v<O>),
39 "optional<T> is trivially copy constructible if T is trivially copy constructible.");
40
41 static_assert(implies(std::is_trivially_move_constructible_v<T>,
42 std::is_trivially_move_constructible_v<O>),
43 "optional<T> is trivially move constructible if T is trivially move constructible");
44
45 static_assert(implies(std::is_trivially_copy_constructible_v<T> &&
46 std::is_trivially_copy_assignable_v<T> &&
47 std::is_trivially_destructible_v<T>,
48
49 std::is_trivially_copy_assignable_v<O>),
50 "optional<T> is trivially copy assignable if T is "
51 "trivially copy constructible, "
52 "trivially copy assignable, and "
53 "trivially destructible");
54
55 static_assert(implies(std::is_trivially_move_constructible_v<T> &&
56 std::is_trivially_move_assignable_v<T> &&
57 std::is_trivially_destructible_v<T>,
58
59 std::is_trivially_move_assignable_v<O>),
60 "optional<T> is trivially move assignable if T is "
61 "trivially move constructible, "
62 "trivially move assignable, and"
63 "trivially destructible.");
64 };
65
sink(Args &&...)66 template <class ...Args> static void sink(Args&&...) {}
67
68 template <class ...TestTypes>
69 struct DoTestsMetafunction {
DoTestsMetafunctionDoTestsMetafunction70 DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); }
71 };
72
73 struct TrivialMoveNonTrivialCopy {
74 TrivialMoveNonTrivialCopy() = default;
TrivialMoveNonTrivialCopyTrivialMoveNonTrivialCopy75 TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {}
76 TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default;
operator =TrivialMoveNonTrivialCopy77 TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; }
78 TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default;
79 };
80
81 struct TrivialCopyNonTrivialMove {
82 TrivialCopyNonTrivialMove() = default;
83 TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default;
TrivialCopyNonTrivialMoveTrivialCopyNonTrivialMove84 TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {}
85 TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default;
operator =TrivialCopyNonTrivialMove86 TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; }
87 };
88
main()89 int main() {
90 sink(
91 ImplicitTypes::ApplyTypes<DoTestsMetafunction>{},
92 ExplicitTypes::ApplyTypes<DoTestsMetafunction>{},
93 NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{},
94 NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{},
95 DoTestsMetafunction<TrivialMoveNonTrivialCopy, TrivialCopyNonTrivialMove>{}
96 );
97 }
98