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
10
11 // <optional>
12
13 // Make sure we properly generate special member functions for optional<T>
14 // based on the properties of T itself.
15
16 #include <optional>
17 #include <type_traits>
18
19 #include "archetypes.h"
20
21 #include "test_macros.h"
22
23
24 template <class T>
25 struct SpecialMemberTest {
26 using O = std::optional<T>;
27
28 static_assert(std::is_default_constructible_v<O>,
29 "optional is always default constructible.");
30
31 static_assert(std::is_copy_constructible_v<O> == std::is_copy_constructible_v<T>,
32 "optional<T> is copy constructible if and only if T is copy constructible.");
33
34 static_assert(std::is_move_constructible_v<O> ==
35 (std::is_copy_constructible_v<T> || std::is_move_constructible_v<T>),
36 "optional<T> is move constructible if and only if T is copy or move constructible.");
37
38 static_assert(std::is_copy_assignable_v<O> ==
39 (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>),
40 "optional<T> is copy assignable if and only if T is both copy "
41 "constructible and copy assignable.");
42
43 static_assert(std::is_move_assignable_v<O> ==
44 ((std::is_move_constructible_v<T> && std::is_move_assignable_v<T>) ||
45 (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>)),
46 "optional<T> is move assignable if and only if T is both move constructible and "
47 "move assignable, or both copy constructible and copy assignable.");
48 };
49
sink(Args &&...)50 template <class ...Args> static void sink(Args&&...) {}
51
52 template <class ...TestTypes>
53 struct DoTestsMetafunction {
DoTestsMetafunctionDoTestsMetafunction54 DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); }
55 };
56
main(int,char **)57 int main(int, char**) {
58 sink(
59 ImplicitTypes::ApplyTypes<DoTestsMetafunction>{},
60 ExplicitTypes::ApplyTypes<DoTestsMetafunction>{},
61 NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{},
62 NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{}
63 );
64 return 0;
65 }
66