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
30constexpr bool implies(bool p, bool q) {
31 return !p || q;
32}
33
34template <class T>
35struct 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
67template <class ...Args> static void sink(Args&&...) {}
68
69template <class ...TestTypes>
70struct DoTestsMetafunction {
71 DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); }
72};
73
74struct 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
82struct 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
90int 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

source code of libcxx/test/std/utilities/optional/optional.object/triviality.pass.cpp