blob: c21c85aad962bbe65665949f989c48fa4ec77f01 [file] [log] [blame]
Louis Dionne1d5f6a82019-01-10 20:06:11 +00001//===----------------------------------------------------------------------===//
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
29constexpr bool implies(bool p, bool q) {
30 return !p || q;
31}
32
33template <class T>
34struct 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
66template <class ...Args> static void sink(Args&&...) {}
67
68template <class ...TestTypes>
69struct DoTestsMetafunction {
70 DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); }
71};
72
73struct TrivialMoveNonTrivialCopy {
74 TrivialMoveNonTrivialCopy() = default;
75 TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {}
76 TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default;
77 TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; }
78 TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default;
79};
80
81struct TrivialCopyNonTrivialMove {
82 TrivialCopyNonTrivialMove() = default;
83 TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default;
84 TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {}
85 TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default;
86 TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; }
87};
88
89int 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}