Home | History | Annotate | Download | only in variant.ctor
      1 // -*- C++ -*-
      2 //===----------------------------------------------------------------------===//
      3 //
      4 //                     The LLVM Compiler Infrastructure
      5 //
      6 // This file is dual licensed under the MIT and the University of Illinois Open
      7 // Source Licenses. See LICENSE.TXT for details.
      8 //
      9 //===----------------------------------------------------------------------===//
     10 
     11 // UNSUPPORTED: c++98, c++03, c++11, c++14
     12 
     13 // <variant>
     14 
     15 // template <class ...Types> class variant;
     16 
     17 // variant(variant const&);
     18 
     19 #include <cassert>
     20 #include <type_traits>
     21 #include <variant>
     22 
     23 #include "test_macros.h"
     24 
     25 struct NonT {
     26   NonT(int v) : value(v) {}
     27   NonT(const NonT &o) : value(o.value) {}
     28   int value;
     29 };
     30 static_assert(!std::is_trivially_copy_constructible<NonT>::value, "");
     31 
     32 struct NoCopy {
     33   NoCopy(const NoCopy &) = delete;
     34 };
     35 
     36 struct MoveOnly {
     37   MoveOnly(const MoveOnly &) = delete;
     38   MoveOnly(MoveOnly &&) = default;
     39 };
     40 
     41 struct MoveOnlyNT {
     42   MoveOnlyNT(const MoveOnlyNT &) = delete;
     43   MoveOnlyNT(MoveOnlyNT &&) {}
     44 };
     45 
     46 #ifndef TEST_HAS_NO_EXCEPTIONS
     47 struct MakeEmptyT {
     48   static int alive;
     49   MakeEmptyT() { ++alive; }
     50   MakeEmptyT(const MakeEmptyT &) {
     51     ++alive;
     52     // Don't throw from the copy constructor since variant's assignment
     53     // operator performs a copy before committing to the assignment.
     54   }
     55   MakeEmptyT(MakeEmptyT &&) { throw 42; }
     56   MakeEmptyT &operator=(const MakeEmptyT &) { throw 42; }
     57   MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
     58   ~MakeEmptyT() { --alive; }
     59 };
     60 
     61 int MakeEmptyT::alive = 0;
     62 
     63 template <class Variant> void makeEmpty(Variant &v) {
     64   Variant v2(std::in_place_type<MakeEmptyT>);
     65   try {
     66     v = v2;
     67     assert(false);
     68   } catch (...) {
     69     assert(v.valueless_by_exception());
     70   }
     71 }
     72 #endif // TEST_HAS_NO_EXCEPTIONS
     73 
     74 void test_copy_ctor_sfinae() {
     75   {
     76     using V = std::variant<int, long>;
     77     static_assert(std::is_copy_constructible<V>::value, "");
     78   }
     79   {
     80     using V = std::variant<int, NoCopy>;
     81     static_assert(!std::is_copy_constructible<V>::value, "");
     82   }
     83   {
     84     using V = std::variant<int, MoveOnly>;
     85     static_assert(!std::is_copy_constructible<V>::value, "");
     86   }
     87   {
     88     using V = std::variant<int, MoveOnlyNT>;
     89     static_assert(!std::is_copy_constructible<V>::value, "");
     90   }
     91 }
     92 
     93 void test_copy_ctor_basic() {
     94   {
     95     std::variant<int> v(std::in_place_index<0>, 42);
     96     std::variant<int> v2 = v;
     97     assert(v2.index() == 0);
     98     assert(std::get<0>(v2) == 42);
     99   }
    100   {
    101     std::variant<int, long> v(std::in_place_index<1>, 42);
    102     std::variant<int, long> v2 = v;
    103     assert(v2.index() == 1);
    104     assert(std::get<1>(v2) == 42);
    105   }
    106   {
    107     std::variant<NonT> v(std::in_place_index<0>, 42);
    108     assert(v.index() == 0);
    109     std::variant<NonT> v2(v);
    110     assert(v2.index() == 0);
    111     assert(std::get<0>(v2).value == 42);
    112   }
    113   {
    114     std::variant<int, NonT> v(std::in_place_index<1>, 42);
    115     assert(v.index() == 1);
    116     std::variant<int, NonT> v2(v);
    117     assert(v2.index() == 1);
    118     assert(std::get<1>(v2).value == 42);
    119   }
    120 }
    121 
    122 void test_copy_ctor_valueless_by_exception() {
    123 #ifndef TEST_HAS_NO_EXCEPTIONS
    124   using V = std::variant<int, MakeEmptyT>;
    125   V v1;
    126   makeEmpty(v1);
    127   const V &cv1 = v1;
    128   V v(cv1);
    129   assert(v.valueless_by_exception());
    130 #endif
    131 }
    132 
    133 template <size_t Idx>
    134 constexpr bool test_constexpr_copy_ctor_extension_imp(
    135     std::variant<long, void*, const int> const& v)
    136 {
    137   auto v2 = v;
    138   return v2.index() == v.index() &&
    139          v2.index() == Idx &&
    140         std::get<Idx>(v2) == std::get<Idx>(v);
    141 }
    142 
    143 void test_constexpr_copy_ctor_extension() {
    144 #ifdef _LIBCPP_VERSION
    145   using V = std::variant<long, void*, const int>;
    146   static_assert(std::is_trivially_copyable<V>::value, "");
    147   static_assert(std::is_trivially_copy_constructible<V>::value, "");
    148   static_assert(test_constexpr_copy_ctor_extension_imp<0>(V(42l)), "");
    149   static_assert(test_constexpr_copy_ctor_extension_imp<1>(V(nullptr)), "");
    150   static_assert(test_constexpr_copy_ctor_extension_imp<2>(V(101)), "");
    151 #endif
    152 }
    153 
    154 int main() {
    155   test_copy_ctor_basic();
    156   test_copy_ctor_valueless_by_exception();
    157   test_copy_ctor_sfinae();
    158   test_constexpr_copy_ctor_extension();
    159 }
    160