Home | History | Annotate | Download | only in optional.object
      1 //===----------------------------------------------------------------------===//
      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
     11 // <optional>
     12 
     13 
     14 #include <optional>
     15 #include <type_traits>
     16 #include <cassert>
     17 
     18 #include "archetypes.hpp"
     19 
     20 template <class T>
     21 struct SpecialMemberTest {
     22     using O = std::optional<T>;
     23 
     24     static_assert(std::is_default_constructible_v<O>,
     25         "optional is always default constructible.");
     26     static_assert(std::is_copy_constructible_v<O> == std::is_copy_constructible_v<T>,
     27         "optional<T> is copy constructible if and only if T is copy constructible.");
     28     static_assert(std::is_move_constructible_v<O> ==
     29         (std::is_copy_constructible_v<T> || std::is_move_constructible_v<T>),
     30         "optional<T> is move constructible if and only if T is copy or move constructible.");
     31     static_assert(std::is_copy_assignable_v<O> ==
     32         (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>),
     33         "optional<T> is copy assignable if and only if T is both copy "
     34         "constructible and copy assignable.");
     35     static_assert(std::is_move_assignable_v<O> ==
     36         ((std::is_move_constructible_v<T> && std::is_move_assignable_v<T>) ||
     37          (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>)),
     38         "optional<T> is move assignable if and only if T is both move constructible and "
     39         "move assignable, or both copy constructible and copy assignable.");
     40 
     41     // The following tests are for not-yet-standardized behavior (P0602):
     42     static_assert(std::is_trivially_destructible_v<O> ==
     43         std::is_trivially_destructible_v<T>,
     44         "optional<T> is trivially destructible if and only if T is.");
     45     static_assert(std::is_trivially_copy_constructible_v<O> ==
     46         std::is_trivially_copy_constructible_v<T>,
     47         "optional<T> is trivially copy constructible if and only if T is.");
     48     static_assert(std::is_trivially_move_constructible_v<O> ==
     49         std::is_trivially_move_constructible_v<T> ||
     50         (!std::is_move_constructible_v<T> && std::is_trivially_copy_constructible_v<T>),
     51         "optional<T> is trivially move constructible if T is trivially move constructible, "
     52         "or if T is trivially copy constructible and is not move constructible.");
     53     static_assert(std::is_trivially_copy_assignable_v<O> ==
     54         (std::is_trivially_destructible_v<T> &&
     55          std::is_trivially_copy_constructible_v<T> &&
     56          std::is_trivially_copy_assignable_v<T>),
     57         "optional<T> is trivially copy assignable if and only if T is trivially destructible, "
     58         "trivially copy constructible, and trivially copy assignable.");
     59     static_assert(std::is_trivially_move_assignable_v<O> ==
     60         (std::is_trivially_destructible_v<T> &&
     61          ((std::is_trivially_move_constructible_v<T> && std::is_trivially_move_assignable_v<T>) ||
     62           ((!std::is_move_constructible_v<T> || !std::is_move_assignable_v<T>) &&
     63            std::is_trivially_copy_constructible_v<T> && std::is_trivially_copy_assignable_v<T>))),
     64         "optional<T> is trivially move assignable if T is trivially destructible, and either "
     65         "(1) trivially move constructible and trivially move assignable, or "
     66         "(2) not move constructible or not move assignable, and "
     67         "trivially copy constructible and trivially copy assignable.");
     68 };
     69 
     70 template <class ...Args> static void sink(Args&&...) {}
     71 
     72 template <class ...TestTypes>
     73 struct DoTestsMetafunction {
     74     DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); }
     75 };
     76 
     77 struct TrivialMoveNonTrivialCopy {
     78     TrivialMoveNonTrivialCopy() = default;
     79     TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {}
     80     TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default;
     81     TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; }
     82     TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default;
     83 };
     84 
     85 struct TrivialCopyNonTrivialMove {
     86     TrivialCopyNonTrivialMove() = default;
     87     TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default;
     88     TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {}
     89     TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default;
     90     TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; }
     91 };
     92 
     93 int main()
     94 {
     95     sink(
     96         ImplicitTypes::ApplyTypes<DoTestsMetafunction>{},
     97         ExplicitTypes::ApplyTypes<DoTestsMetafunction>{},
     98         NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{},
     99         NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{},
    100         DoTestsMetafunction<TrivialMoveNonTrivialCopy, TrivialCopyNonTrivialMove>{}
    101     );
    102 }
    103