libcxx

libcxx mirror with random patches
git clone https://git.neptards.moe/neptards/libcxx.git
Log | Files | Refs

copy.pass.cpp (8209B)


      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 // XFAIL: availability=macosx10.13
     14 // XFAIL: availability=macosx10.12
     15 // XFAIL: availability=macosx10.11
     16 // XFAIL: availability=macosx10.10
     17 // XFAIL: availability=macosx10.9
     18 // XFAIL: availability=macosx10.8
     19 // XFAIL: availability=macosx10.7
     20 
     21 // <variant>
     22 
     23 // template <class ...Types> class variant;
     24 
     25 // variant(variant const&); // constexpr in C++20
     26 
     27 #include <cassert>
     28 #include <type_traits>
     29 #include <variant>
     30 
     31 #include "test_macros.h"
     32 #include "test_workarounds.h"
     33 
     34 struct NonT {
     35   NonT(int v) : value(v) {}
     36   NonT(const NonT &o) : value(o.value) {}
     37   int value;
     38 };
     39 static_assert(!std::is_trivially_copy_constructible<NonT>::value, "");
     40 
     41 struct NoCopy {
     42   NoCopy(const NoCopy &) = delete;
     43 };
     44 
     45 struct MoveOnly {
     46   MoveOnly(const MoveOnly &) = delete;
     47   MoveOnly(MoveOnly &&) = default;
     48 };
     49 
     50 struct MoveOnlyNT {
     51   MoveOnlyNT(const MoveOnlyNT &) = delete;
     52   MoveOnlyNT(MoveOnlyNT &&) {}
     53 };
     54 
     55 struct NTCopy {
     56   constexpr NTCopy(int v) : value(v) {}
     57   NTCopy(const NTCopy &that) : value(that.value) {}
     58   NTCopy(NTCopy &&) = delete;
     59   int value;
     60 };
     61 
     62 static_assert(!std::is_trivially_copy_constructible<NTCopy>::value, "");
     63 static_assert(std::is_copy_constructible<NTCopy>::value, "");
     64 
     65 struct TCopy {
     66   constexpr TCopy(int v) : value(v) {}
     67   TCopy(TCopy const &) = default;
     68   TCopy(TCopy &&) = delete;
     69   int value;
     70 };
     71 
     72 static_assert(std::is_trivially_copy_constructible<TCopy>::value, "");
     73 
     74 struct TCopyNTMove {
     75   constexpr TCopyNTMove(int v) : value(v) {}
     76   TCopyNTMove(const TCopyNTMove&) = default;
     77   TCopyNTMove(TCopyNTMove&& that) : value(that.value) { that.value = -1; }
     78   int value;
     79 };
     80 
     81 static_assert(std::is_trivially_copy_constructible<TCopyNTMove>::value, "");
     82 
     83 #ifndef TEST_HAS_NO_EXCEPTIONS
     84 struct MakeEmptyT {
     85   static int alive;
     86   MakeEmptyT() { ++alive; }
     87   MakeEmptyT(const MakeEmptyT &) {
     88     ++alive;
     89     // Don't throw from the copy constructor since variant's assignment
     90     // operator performs a copy before committing to the assignment.
     91   }
     92   MakeEmptyT(MakeEmptyT &&) { throw 42; }
     93   MakeEmptyT &operator=(const MakeEmptyT &) { throw 42; }
     94   MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
     95   ~MakeEmptyT() { --alive; }
     96 };
     97 
     98 int MakeEmptyT::alive = 0;
     99 
    100 template <class Variant> void makeEmpty(Variant &v) {
    101   Variant v2(std::in_place_type<MakeEmptyT>);
    102   try {
    103     v = std::move(v2);
    104     assert(false);
    105   } catch (...) {
    106     assert(v.valueless_by_exception());
    107   }
    108 }
    109 #endif // TEST_HAS_NO_EXCEPTIONS
    110 
    111 void test_copy_ctor_sfinae() {
    112   {
    113     using V = std::variant<int, long>;
    114     static_assert(std::is_copy_constructible<V>::value, "");
    115   }
    116   {
    117     using V = std::variant<int, NoCopy>;
    118     static_assert(!std::is_copy_constructible<V>::value, "");
    119   }
    120   {
    121     using V = std::variant<int, MoveOnly>;
    122     static_assert(!std::is_copy_constructible<V>::value, "");
    123   }
    124   {
    125     using V = std::variant<int, MoveOnlyNT>;
    126     static_assert(!std::is_copy_constructible<V>::value, "");
    127   }
    128 
    129   // Make sure we properly propagate triviality (see P0602R4).
    130 #if TEST_STD_VER > 17
    131   {
    132     using V = std::variant<int, long>;
    133     static_assert(std::is_trivially_copy_constructible<V>::value, "");
    134   }
    135   {
    136     using V = std::variant<int, NTCopy>;
    137     static_assert(!std::is_trivially_copy_constructible<V>::value, "");
    138     static_assert(std::is_copy_constructible<V>::value, "");
    139   }
    140   {
    141     using V = std::variant<int, TCopy>;
    142     static_assert(std::is_trivially_copy_constructible<V>::value, "");
    143   }
    144   {
    145     using V = std::variant<int, TCopyNTMove>;
    146     static_assert(std::is_trivially_copy_constructible<V>::value, "");
    147   }
    148 #endif // > C++17
    149 }
    150 
    151 void test_copy_ctor_basic() {
    152   {
    153     std::variant<int> v(std::in_place_index<0>, 42);
    154     std::variant<int> v2 = v;
    155     assert(v2.index() == 0);
    156     assert(std::get<0>(v2) == 42);
    157   }
    158   {
    159     std::variant<int, long> v(std::in_place_index<1>, 42);
    160     std::variant<int, long> v2 = v;
    161     assert(v2.index() == 1);
    162     assert(std::get<1>(v2) == 42);
    163   }
    164   {
    165     std::variant<NonT> v(std::in_place_index<0>, 42);
    166     assert(v.index() == 0);
    167     std::variant<NonT> v2(v);
    168     assert(v2.index() == 0);
    169     assert(std::get<0>(v2).value == 42);
    170   }
    171   {
    172     std::variant<int, NonT> v(std::in_place_index<1>, 42);
    173     assert(v.index() == 1);
    174     std::variant<int, NonT> v2(v);
    175     assert(v2.index() == 1);
    176     assert(std::get<1>(v2).value == 42);
    177   }
    178 
    179   // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4).
    180 #if TEST_STD_VER > 17
    181   {
    182     constexpr std::variant<int> v(std::in_place_index<0>, 42);
    183     static_assert(v.index() == 0, "");
    184     constexpr std::variant<int> v2 = v;
    185     static_assert(v2.index() == 0, "");
    186     static_assert(std::get<0>(v2) == 42, "");
    187   }
    188   {
    189     constexpr std::variant<int, long> v(std::in_place_index<1>, 42);
    190     static_assert(v.index() == 1, "");
    191     constexpr std::variant<int, long> v2 = v;
    192     static_assert(v2.index() == 1, "");
    193     static_assert(std::get<1>(v2) == 42, "");
    194   }
    195   {
    196     constexpr std::variant<TCopy> v(std::in_place_index<0>, 42);
    197     static_assert(v.index() == 0, "");
    198     constexpr std::variant<TCopy> v2(v);
    199     static_assert(v2.index() == 0, "");
    200     static_assert(std::get<0>(v2).value == 42, "");
    201   }
    202   {
    203     constexpr std::variant<int, TCopy> v(std::in_place_index<1>, 42);
    204     static_assert(v.index() == 1, "");
    205     constexpr std::variant<int, TCopy> v2(v);
    206     static_assert(v2.index() == 1, "");
    207     static_assert(std::get<1>(v2).value == 42, "");
    208   }
    209   {
    210     constexpr std::variant<TCopyNTMove> v(std::in_place_index<0>, 42);
    211     static_assert(v.index() == 0, "");
    212     constexpr std::variant<TCopyNTMove> v2(v);
    213     static_assert(v2.index() == 0, "");
    214     static_assert(std::get<0>(v2).value == 42, "");
    215   }
    216   {
    217     constexpr std::variant<int, TCopyNTMove> v(std::in_place_index<1>, 42);
    218     static_assert(v.index() == 1, "");
    219     constexpr std::variant<int, TCopyNTMove> v2(v);
    220     static_assert(v2.index() == 1, "");
    221     static_assert(std::get<1>(v2).value == 42, "");
    222   }
    223 #endif // > C++17
    224 }
    225 
    226 void test_copy_ctor_valueless_by_exception() {
    227 #ifndef TEST_HAS_NO_EXCEPTIONS
    228   using V = std::variant<int, MakeEmptyT>;
    229   V v1;
    230   makeEmpty(v1);
    231   const V &cv1 = v1;
    232   V v(cv1);
    233   assert(v.valueless_by_exception());
    234 #endif // TEST_HAS_NO_EXCEPTIONS
    235 }
    236 
    237 template <size_t Idx>
    238 constexpr bool test_constexpr_copy_ctor_imp(std::variant<long, void*, const int> const& v) {
    239   auto v2 = v;
    240   return v2.index() == v.index() &&
    241          v2.index() == Idx &&
    242          std::get<Idx>(v2) == std::get<Idx>(v);
    243 }
    244 
    245 void test_constexpr_copy_ctor() {
    246   // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4).
    247 #if TEST_STD_VER > 17
    248   using V = std::variant<long, void*, const int>;
    249 #ifdef TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
    250   static_assert(std::is_trivially_destructible<V>::value, "");
    251   static_assert(std::is_trivially_copy_constructible<V>::value, "");
    252   static_assert(std::is_trivially_move_constructible<V>::value, "");
    253   static_assert(!std::is_copy_assignable<V>::value, "");
    254   static_assert(!std::is_move_assignable<V>::value, "");
    255 #else // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
    256   static_assert(std::is_trivially_copyable<V>::value, "");
    257 #endif // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
    258   static_assert(test_constexpr_copy_ctor_imp<0>(V(42l)), "");
    259   static_assert(test_constexpr_copy_ctor_imp<1>(V(nullptr)), "");
    260   static_assert(test_constexpr_copy_ctor_imp<2>(V(101)), "");
    261 #endif // > C++17
    262 }
    263 
    264 int main() {
    265   test_copy_ctor_basic();
    266   test_copy_ctor_valueless_by_exception();
    267   test_copy_ctor_sfinae();
    268   test_constexpr_copy_ctor();
    269 #if 0
    270 // disable this for the moment; it fails on older compilers.
    271 //  Need to figure out which compilers will support it.
    272 { // This is the motivating example from P0739R0
    273   std::variant<int, double> v1(3);
    274   std::variant v2 = v1;
    275   (void) v2;
    276 }
    277 #endif
    278 }