xref: /llvm-project/libcxx/test/std/utilities/optional/optional.object/triviality.pass.cpp (revision 31cbe0f240f660f15602c96b787c58a26f17e179)
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