Home | History | Annotate | Download | only in variant.get
      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 <size_t I, class... Types>
     24 //   constexpr variant_alternative_t<I, variant<Types...>>&
     25 //   get(variant<Types...>& v);
     26 // template <size_t I, class... Types>
     27 //   constexpr variant_alternative_t<I, variant<Types...>>&&
     28 //   get(variant<Types...>&& v);
     29 // template <size_t I, class... Types>
     30 //   constexpr variant_alternative_t<I, variant<Types...>> const& get(const
     31 //   variant<Types...>& v);
     32 // template <size_t I, class... Types>
     33 //  constexpr variant_alternative_t<I, variant<Types...>> const&& get(const
     34 //  variant<Types...>&& v);
     35 
     36 #include "test_macros.h"
     37 #include "variant_test_helpers.hpp"
     38 #include <cassert>
     39 #include <type_traits>
     40 #include <utility>
     41 #include <variant>
     42 
     43 void test_const_lvalue_get() {
     44   {
     45     using V = std::variant<int, const long>;
     46     constexpr V v(42);
     47 #ifndef __clang__ // Avoid https://bugs.llvm.org/show_bug.cgi?id=15481
     48     ASSERT_NOEXCEPT(std::get<0>(v));
     49 #endif
     50     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
     51     static_assert(std::get<0>(v) == 42, "");
     52   }
     53   {
     54     using V = std::variant<int, const long>;
     55     const V v(42);
     56     ASSERT_NOT_NOEXCEPT(std::get<0>(v));
     57     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
     58     assert(std::get<0>(v) == 42);
     59   }
     60   {
     61     using V = std::variant<int, const long>;
     62     constexpr V v(42l);
     63 #ifndef __clang__ // Avoid https://bugs.llvm.org/show_bug.cgi?id=15481
     64     ASSERT_NOEXCEPT(std::get<1>(v));
     65 #endif
     66     ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &);
     67     static_assert(std::get<1>(v) == 42, "");
     68   }
     69   {
     70     using V = std::variant<int, const long>;
     71     const V v(42l);
     72     ASSERT_NOT_NOEXCEPT(std::get<1>(v));
     73     ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &);
     74     assert(std::get<1>(v) == 42);
     75   }
     76 // FIXME: Remove these once reference support is reinstated
     77 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
     78   {
     79     using V = std::variant<int &>;
     80     int x = 42;
     81     const V v(x);
     82     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
     83     assert(&std::get<0>(v) == &x);
     84   }
     85   {
     86     using V = std::variant<int &&>;
     87     int x = 42;
     88     const V v(std::move(x));
     89     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
     90     assert(&std::get<0>(v) == &x);
     91   }
     92   {
     93     using V = std::variant<const int &&>;
     94     int x = 42;
     95     const V v(std::move(x));
     96     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
     97     assert(&std::get<0>(v) == &x);
     98   }
     99 #endif
    100 }
    101 
    102 void test_lvalue_get() {
    103   {
    104     using V = std::variant<int, const long>;
    105     V v(42);
    106     ASSERT_NOT_NOEXCEPT(std::get<0>(v));
    107     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
    108     assert(std::get<0>(v) == 42);
    109   }
    110   {
    111     using V = std::variant<int, const long>;
    112     V v(42l);
    113     ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &);
    114     assert(std::get<1>(v) == 42);
    115   }
    116 // FIXME: Remove these once reference support is reinstated
    117 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
    118   {
    119     using V = std::variant<int &>;
    120     int x = 42;
    121     V v(x);
    122     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
    123     assert(&std::get<0>(v) == &x);
    124   }
    125   {
    126     using V = std::variant<const int &>;
    127     int x = 42;
    128     V v(x);
    129     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
    130     assert(&std::get<0>(v) == &x);
    131   }
    132   {
    133     using V = std::variant<int &&>;
    134     int x = 42;
    135     V v(std::move(x));
    136     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
    137     assert(&std::get<0>(v) == &x);
    138   }
    139   {
    140     using V = std::variant<const int &&>;
    141     int x = 42;
    142     V v(std::move(x));
    143     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
    144     assert(&std::get<0>(v) == &x);
    145   }
    146 #endif
    147 }
    148 
    149 void test_rvalue_get() {
    150   {
    151     using V = std::variant<int, const long>;
    152     V v(42);
    153     ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v)));
    154     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&);
    155     assert(std::get<0>(std::move(v)) == 42);
    156   }
    157   {
    158     using V = std::variant<int, const long>;
    159     V v(42l);
    160     ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&);
    161     assert(std::get<1>(std::move(v)) == 42);
    162   }
    163 // FIXME: Remove these once reference support is reinstated
    164 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
    165   {
    166     using V = std::variant<int &>;
    167     int x = 42;
    168     V v(x);
    169     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &);
    170     assert(&std::get<0>(std::move(v)) == &x);
    171   }
    172   {
    173     using V = std::variant<const int &>;
    174     int x = 42;
    175     V v(x);
    176     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &);
    177     assert(&std::get<0>(std::move(v)) == &x);
    178   }
    179   {
    180     using V = std::variant<int &&>;
    181     int x = 42;
    182     V v(std::move(x));
    183     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&);
    184     int &&xref = std::get<0>(std::move(v));
    185     assert(&xref == &x);
    186   }
    187   {
    188     using V = std::variant<const int &&>;
    189     int x = 42;
    190     V v(std::move(x));
    191     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&);
    192     const int &&xref = std::get<0>(std::move(v));
    193     assert(&xref == &x);
    194   }
    195 #endif
    196 }
    197 
    198 void test_const_rvalue_get() {
    199   {
    200     using V = std::variant<int, const long>;
    201     const V v(42);
    202     ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v)));
    203     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&);
    204     assert(std::get<0>(std::move(v)) == 42);
    205   }
    206   {
    207     using V = std::variant<int, const long>;
    208     const V v(42l);
    209     ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&);
    210     assert(std::get<1>(std::move(v)) == 42);
    211   }
    212 // FIXME: Remove these once reference support is reinstated
    213 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
    214   {
    215     using V = std::variant<int &>;
    216     int x = 42;
    217     const V v(x);
    218     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &);
    219     assert(&std::get<0>(std::move(v)) == &x);
    220   }
    221   {
    222     using V = std::variant<const int &>;
    223     int x = 42;
    224     const V v(x);
    225     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &);
    226     assert(&std::get<0>(std::move(v)) == &x);
    227   }
    228   {
    229     using V = std::variant<int &&>;
    230     int x = 42;
    231     const V v(std::move(x));
    232     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&);
    233     int &&xref = std::get<0>(std::move(v));
    234     assert(&xref == &x);
    235   }
    236   {
    237     using V = std::variant<const int &&>;
    238     int x = 42;
    239     const V v(std::move(x));
    240     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&);
    241     const int &&xref = std::get<0>(std::move(v));
    242     assert(&xref == &x);
    243   }
    244 #endif
    245 }
    246 
    247 template <std::size_t I> using Idx = std::integral_constant<size_t, I>;
    248 
    249 void test_throws_for_all_value_categories() {
    250 #ifndef TEST_HAS_NO_EXCEPTIONS
    251   using V = std::variant<int, long>;
    252   V v0(42);
    253   const V &cv0 = v0;
    254   assert(v0.index() == 0);
    255   V v1(42l);
    256   const V &cv1 = v1;
    257   assert(v1.index() == 1);
    258   std::integral_constant<size_t, 0> zero;
    259   std::integral_constant<size_t, 1> one;
    260   auto test = [](auto idx, auto &&v) {
    261     using Idx = decltype(idx);
    262     try {
    263       TEST_IGNORE_NODISCARD std::get<Idx::value>(std::forward<decltype(v)>(v));
    264     } catch (const std::bad_variant_access &) {
    265       return true;
    266     } catch (...) { /* ... */
    267     }
    268     return false;
    269   };
    270   { // lvalue test cases
    271     assert(test(one, v0));
    272     assert(test(zero, v1));
    273   }
    274   { // const lvalue test cases
    275     assert(test(one, cv0));
    276     assert(test(zero, cv1));
    277   }
    278   { // rvalue test cases
    279     assert(test(one, std::move(v0)));
    280     assert(test(zero, std::move(v1)));
    281   }
    282   { // const rvalue test cases
    283     assert(test(one, std::move(cv0)));
    284     assert(test(zero, std::move(cv1)));
    285   }
    286 #endif
    287 }
    288 
    289 int main() {
    290   test_const_lvalue_get();
    291   test_lvalue_get();
    292   test_rvalue_get();
    293   test_const_rvalue_get();
    294   test_throws_for_all_value_categories();
    295 }
    296