blob: f53d86000e7c712f0725f2d45b74e32cc3b34187 [file] [log] [blame]
Louis Dionne1d5f6a82019-01-10 20:06:11 +00001//===----------------------------------------------------------------------===//
2//
Chandler Carruth57b08b02019-01-19 10:56:40 +00003// 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
Louis Dionne1d5f6a82019-01-10 20:06:11 +00006//
7//===----------------------------------------------------------------------===//
8
9// UNSUPPORTED: c++98, 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.hpp"
26
27
28constexpr bool implies(bool p, bool q) {
29 return !p || q;
30}
31
32template <class T>
33struct SpecialMemberTest {
34 using O = std::optional<T>;
35
36 static_assert(implies(std::is_trivially_copy_constructible_v<T>,
37 std::is_trivially_copy_constructible_v<O>),
38 "optional<T> is trivially copy constructible if T is trivially copy constructible.");
39
40 static_assert(implies(std::is_trivially_move_constructible_v<T>,
41 std::is_trivially_move_constructible_v<O>),
42 "optional<T> is trivially move constructible if T is trivially move constructible");
43
44 static_assert(implies(std::is_trivially_copy_constructible_v<T> &&
45 std::is_trivially_copy_assignable_v<T> &&
46 std::is_trivially_destructible_v<T>,
47
48 std::is_trivially_copy_assignable_v<O>),
49 "optional<T> is trivially copy assignable if T is "
50 "trivially copy constructible, "
51 "trivially copy assignable, and "
52 "trivially destructible");
53
54 static_assert(implies(std::is_trivially_move_constructible_v<T> &&
55 std::is_trivially_move_assignable_v<T> &&
56 std::is_trivially_destructible_v<T>,
57
58 std::is_trivially_move_assignable_v<O>),
59 "optional<T> is trivially move assignable if T is "
60 "trivially move constructible, "
61 "trivially move assignable, and"
62 "trivially destructible.");
63};
64
65template <class ...Args> static void sink(Args&&...) {}
66
67template <class ...TestTypes>
68struct DoTestsMetafunction {
69 DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); }
70};
71
72struct TrivialMoveNonTrivialCopy {
73 TrivialMoveNonTrivialCopy() = default;
74 TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {}
75 TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default;
76 TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; }
77 TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default;
78};
79
80struct TrivialCopyNonTrivialMove {
81 TrivialCopyNonTrivialMove() = default;
82 TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default;
83 TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {}
84 TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default;
85 TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; }
86};
87
JF Bastien2df59c52019-02-04 20:31:13 +000088int main(int, char**) {
Louis Dionne1d5f6a82019-01-10 20:06:11 +000089 sink(
90 ImplicitTypes::ApplyTypes<DoTestsMetafunction>{},
91 ExplicitTypes::ApplyTypes<DoTestsMetafunction>{},
92 NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{},
93 NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{},
94 DoTestsMetafunction<TrivialMoveNonTrivialCopy, TrivialCopyNonTrivialMove>{}
95 );
JF Bastien2df59c52019-02-04 20:31:13 +000096 return 0;
Louis Dionne1d5f6a82019-01-10 20:06:11 +000097}