xref: /llvm-project/libcxx/test/std/utilities/variant/variant.get/get_index.pass.cpp (revision dfde6e89ecc10b1f1eebdb0e409ef1a084030a6c)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14
10 
11 // <variant>
12 
13 // template <size_t I, class... Types>
14 //   constexpr variant_alternative_t<I, variant<Types...>>&
15 //   get(variant<Types...>& v);
16 // template <size_t I, class... Types>
17 //   constexpr variant_alternative_t<I, variant<Types...>>&&
18 //   get(variant<Types...>&& v);
19 // template <size_t I, class... Types>
20 //   constexpr variant_alternative_t<I, variant<Types...>> const& get(const
21 //   variant<Types...>& v);
22 // template <size_t I, class... Types>
23 //  constexpr variant_alternative_t<I, variant<Types...>> const&& get(const
24 //  variant<Types...>&& v);
25 
26 #include "test_macros.h"
27 #include "test_workarounds.h"
28 #include "variant_test_helpers.h"
29 #include <cassert>
30 #include <type_traits>
31 #include <utility>
32 #include <variant>
33 
test_const_lvalue_get()34 void test_const_lvalue_get() {
35   {
36     using V = std::variant<int, const long>;
37     constexpr V v(42);
38     ASSERT_NOT_NOEXCEPT(std::get<0>(v));
39     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
40     static_assert(std::get<0>(v) == 42, "");
41   }
42   {
43     using V = std::variant<int, const long>;
44     const V v(42);
45     ASSERT_NOT_NOEXCEPT(std::get<0>(v));
46     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
47     assert(std::get<0>(v) == 42);
48   }
49   {
50     using V = std::variant<int, const long>;
51     constexpr V v(42l);
52     ASSERT_NOT_NOEXCEPT(std::get<1>(v));
53     ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &);
54     static_assert(std::get<1>(v) == 42, "");
55   }
56   {
57     using V = std::variant<int, const long>;
58     const V v(42l);
59     ASSERT_NOT_NOEXCEPT(std::get<1>(v));
60     ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &);
61     assert(std::get<1>(v) == 42);
62   }
63 }
64 
test_lvalue_get()65 void test_lvalue_get() {
66   {
67     using V = std::variant<int, const long>;
68     V v(42);
69     ASSERT_NOT_NOEXCEPT(std::get<0>(v));
70     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
71     assert(std::get<0>(v) == 42);
72   }
73   {
74     using V = std::variant<int, const long>;
75     V v(42l);
76     ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &);
77     assert(std::get<1>(v) == 42);
78   }
79 }
80 
test_rvalue_get()81 void test_rvalue_get() {
82   {
83     using V = std::variant<int, const long>;
84     V v(42);
85     ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v)));
86     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&);
87     assert(std::get<0>(std::move(v)) == 42);
88   }
89   {
90     using V = std::variant<int, const long>;
91     V v(42l);
92     ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&);
93     assert(std::get<1>(std::move(v)) == 42);
94   }
95 }
96 
test_const_rvalue_get()97 void test_const_rvalue_get() {
98   {
99     using V = std::variant<int, const long>;
100     const V v(42);
101     ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v)));
102     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&);
103     assert(std::get<0>(std::move(v)) == 42);
104   }
105   {
106     using V = std::variant<int, const long>;
107     const V v(42l);
108     ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&);
109     assert(std::get<1>(std::move(v)) == 42);
110   }
111 }
112 
113 template <std::size_t I> using Idx = std::integral_constant<std::size_t, I>;
114 
test_throws_for_all_value_categories()115 void test_throws_for_all_value_categories() {
116 #ifndef TEST_HAS_NO_EXCEPTIONS
117   using V = std::variant<int, long>;
118   V v0(42);
119   const V &cv0 = v0;
120   assert(v0.index() == 0);
121   V v1(42l);
122   const V &cv1 = v1;
123   assert(v1.index() == 1);
124   std::integral_constant<std::size_t, 0> zero;
125   std::integral_constant<std::size_t, 1> one;
126   auto test = [](auto idx, auto &&v) {
127     using Idx = decltype(idx);
128     try {
129       TEST_IGNORE_NODISCARD std::get<Idx::value>(std::forward<decltype(v)>(v));
130     } catch (const std::bad_variant_access &) {
131       return true;
132     } catch (...) { /* ... */
133     }
134     return false;
135   };
136   { // lvalue test cases
137     assert(test(one, v0));
138     assert(test(zero, v1));
139   }
140   { // const lvalue test cases
141     assert(test(one, cv0));
142     assert(test(zero, cv1));
143   }
144   { // rvalue test cases
145     assert(test(one, std::move(v0)));
146     assert(test(zero, std::move(v1)));
147   }
148   { // const rvalue test cases
149     assert(test(one, std::move(cv0)));
150     assert(test(zero, std::move(cv1)));
151   }
152 #endif
153 }
154 
main(int,char **)155 int main(int, char**) {
156   test_const_lvalue_get();
157   test_lvalue_get();
158   test_rvalue_get();
159   test_const_rvalue_get();
160   test_throws_for_all_value_categories();
161 
162   return 0;
163 }
164