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