Bug 1919778 - Flag EnumeratedArray variable from dom/media/ipc/RemoteDecoderManagerCh...
[gecko.git] / mfbt / tests / TestVariant.cpp
blob552be723b89a64652f19273edf43f3b2277854be
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include <type_traits>
9 #include "mozilla/UniquePtr.h"
10 #include "mozilla/Variant.h"
12 #include <tuple>
14 using mozilla::MakeUnique;
15 using mozilla::UniquePtr;
16 using mozilla::Variant;
18 struct Destroyer {
19 static int destroyedCount;
20 ~Destroyer() { destroyedCount++; }
23 int Destroyer::destroyedCount = 0;
25 static void testDetails() {
26 printf("testDetails\n");
28 using mozilla::detail::Nth;
30 // Test Nth with a list of 1 item.
31 static_assert(std::is_same_v<typename Nth<0, int>::Type, int>,
32 "Nth<0, int>::Type should be int");
34 // Test Nth with a list of more than 1 item.
35 static_assert(std::is_same_v<typename Nth<0, int, char>::Type, int>,
36 "Nth<0, int, char>::Type should be int");
37 static_assert(std::is_same_v<typename Nth<1, int, char>::Type, char>,
38 "Nth<1, int, char>::Type should be char");
40 using mozilla::detail::SelectVariantType;
42 // SelectVariantType for zero items (shouldn't happen, but `count` should
43 // still work ok.)
44 static_assert(SelectVariantType<int, char>::count == 0,
45 "SelectVariantType<int, char>::count should be 0");
47 // SelectVariantType for 1 type, for all combinations from/to T, const T,
48 // const T&, T&&
49 // - type to type
50 static_assert(std::is_same_v<typename SelectVariantType<int, int>::Type, int>,
51 "SelectVariantType<int, int>::Type should be int");
52 static_assert(SelectVariantType<int, int>::count == 1,
53 "SelectVariantType<int, int>::count should be 1");
55 // - type to const type
56 static_assert(std::is_same_v<typename SelectVariantType<int, const int>::Type,
57 const int>,
58 "SelectVariantType<int, const int>::Type should be const int");
59 static_assert(SelectVariantType<int, const int>::count == 1,
60 "SelectVariantType<int, const int>::count should be 1");
62 // - type to const type&
63 static_assert(
64 std::is_same_v<typename SelectVariantType<int, const int&>::Type,
65 const int&>,
66 "SelectVariantType<int, const int&>::Type should be const int&");
67 static_assert(SelectVariantType<int, const int&>::count == 1,
68 "SelectVariantType<int, const int&>::count should be 1");
70 // - type to type&&
71 static_assert(
72 std::is_same_v<typename SelectVariantType<int, int&&>::Type, int&&>,
73 "SelectVariantType<int, int&&>::Type should be int&&");
74 static_assert(SelectVariantType<int, int&&>::count == 1,
75 "SelectVariantType<int, int&&>::count should be 1");
77 // - const type to type
78 static_assert(
79 std::is_same_v<typename SelectVariantType<const int, int>::Type, int>,
80 "SelectVariantType<const int, int>::Type should be int");
81 static_assert(SelectVariantType<const int, int>::count == 1,
82 "SelectVariantType<const int, int>::count should be 1");
84 // - const type to const type
85 static_assert(
86 std::is_same_v<typename SelectVariantType<const int, const int>::Type,
87 const int>,
88 "SelectVariantType<const int, const int>::Type should be const int");
89 static_assert(SelectVariantType<const int, const int>::count == 1,
90 "SelectVariantType<const int, const int>::count should be 1");
92 // - const type to const type&
93 static_assert(
94 std::is_same_v<typename SelectVariantType<const int, const int&>::Type,
95 const int&>,
96 "SelectVariantType<const int, const int&>::Type should be const int&");
97 static_assert(SelectVariantType<const int, const int&>::count == 1,
98 "SelectVariantType<const int, const int&>::count should be 1");
100 // - const type to type&&
101 static_assert(
102 std::is_same_v<typename SelectVariantType<const int, int&&>::Type, int&&>,
103 "SelectVariantType<const int, int&&>::Type should be int&&");
104 static_assert(SelectVariantType<const int, int&&>::count == 1,
105 "SelectVariantType<const int, int&&>::count should be 1");
107 // - const type& to type
108 static_assert(
109 std::is_same_v<typename SelectVariantType<const int&, int>::Type, int>,
110 "SelectVariantType<const int&, int>::Type should be int");
111 static_assert(SelectVariantType<const int&, int>::count == 1,
112 "SelectVariantType<const int&, int>::count should be 1");
114 // - const type& to const type
115 static_assert(
116 std::is_same_v<typename SelectVariantType<const int&, const int>::Type,
117 const int>,
118 "SelectVariantType<const int&, const int>::Type should be const int");
119 static_assert(SelectVariantType<const int&, const int>::count == 1,
120 "SelectVariantType<const int&, const int>::count should be 1");
122 // - const type& to const type&
123 static_assert(
124 std::is_same_v<typename SelectVariantType<const int&, const int&>::Type,
125 const int&>,
126 "SelectVariantType<const int&, const int&>::Type should be const int&");
127 static_assert(SelectVariantType<const int&, const int&>::count == 1,
128 "SelectVariantType<const int&, const int&>::count should be 1");
130 // - const type& to type&&
131 static_assert(
132 std::is_same_v<typename SelectVariantType<const int&, int&&>::Type,
133 int&&>,
134 "SelectVariantType<const int&, int&&>::Type should be int&&");
135 static_assert(SelectVariantType<const int&, int&&>::count == 1,
136 "SelectVariantType<const int&, int&&>::count should be 1");
138 // - type&& to type
139 static_assert(
140 std::is_same_v<typename SelectVariantType<int&&, int>::Type, int>,
141 "SelectVariantType<int&&, int>::Type should be int");
142 static_assert(SelectVariantType<int&&, int>::count == 1,
143 "SelectVariantType<int&&, int>::count should be 1");
145 // - type&& to const type
146 static_assert(
147 std::is_same_v<typename SelectVariantType<int&&, const int>::Type,
148 const int>,
149 "SelectVariantType<int&&, const int>::Type should be const int");
150 static_assert(SelectVariantType<int&&, const int>::count == 1,
151 "SelectVariantType<int&&, const int>::count should be 1");
153 // - type&& to const type&
154 static_assert(
155 std::is_same_v<typename SelectVariantType<int&&, const int&>::Type,
156 const int&>,
157 "SelectVariantType<int&&, const int&>::Type should be const int&");
158 static_assert(SelectVariantType<int&&, const int&>::count == 1,
159 "SelectVariantType<int&&, const int&>::count should be 1");
161 // - type&& to type&&
162 static_assert(
163 std::is_same_v<typename SelectVariantType<int&&, int&&>::Type, int&&>,
164 "SelectVariantType<int&&, int&&>::Type should be int&&");
165 static_assert(SelectVariantType<int&&, int&&>::count == 1,
166 "SelectVariantType<int&&, int&&>::count should be 1");
168 // SelectVariantType for two different types.
169 // (Don't test all combinations, trust that the above tests are sufficient.)
170 static_assert(
171 std::is_same_v<typename SelectVariantType<int, int, char>::Type, int>,
172 "SelectVariantType<int, int, char>::Type should be int");
173 static_assert(SelectVariantType<int, int, char>::count == 1,
174 "SelectVariantType<int, int, char>::count should be 1");
175 static_assert(
176 std::is_same_v<typename SelectVariantType<char, int, char>::Type, char>,
177 "SelectVariantType<char, int, char>::Type should be char");
178 static_assert(SelectVariantType<char, int, char>::count == 1,
179 "SelectVariantType<char, int, char>::count should be 1");
181 // SelectVariantType for two identical types.
182 static_assert(
183 std::is_same_v<typename SelectVariantType<int, int, int>::Type, int>,
184 "SelectVariantType<int, int, int>::Type should be int");
185 static_assert(SelectVariantType<int, int, int>::count == 2,
186 "SelectVariantType<int, int, int>::count should be 2");
188 // SelectVariantType for two identical types, with others around.
189 static_assert(
190 std::is_same_v<typename SelectVariantType<int, char, int, int>::Type,
191 int>,
192 "SelectVariantType<int, char, int, int>::Type should be int");
193 static_assert(SelectVariantType<int, char, int, int>::count == 2,
194 "SelectVariantType<int, char, int, int>::count should be 2");
196 static_assert(
197 std::is_same_v<typename SelectVariantType<int, int, char, int>::Type,
198 int>,
199 "SelectVariantType<int, int, char, int>::Type should be int");
200 static_assert(SelectVariantType<int, int, char, int>::count == 2,
201 "SelectVariantType<int, int, char, int>::count should be 2");
203 static_assert(
204 std::is_same_v<typename SelectVariantType<int, int, int, char>::Type,
205 int>,
206 "SelectVariantType<int, int, int, char>::Type should be int");
207 static_assert(SelectVariantType<int, int, int, char>::count == 2,
208 "SelectVariantType<int, int, int, char>::count should be 2");
210 static_assert(
211 std::is_same_v<
212 typename SelectVariantType<int, char, int, char, int, char>::Type,
213 int>,
214 "SelectVariantType<int, char, int, char, int, char>::Type should be int");
215 static_assert(
216 SelectVariantType<int, char, int, char, int, char>::count == 2,
217 "SelectVariantType<int, char, int, char, int, char>::count should be 2");
219 // SelectVariantType for two identically-selectable types (first one wins!).
220 static_assert(
221 std::is_same_v<typename SelectVariantType<int, int, const int>::Type,
222 int>,
223 "SelectVariantType<int, int, const int>::Type should be int");
224 static_assert(SelectVariantType<int, int, const int>::count == 2,
225 "SelectVariantType<int, int, const int>::count should be 2");
226 static_assert(
227 std::is_same_v<typename SelectVariantType<int, const int, int>::Type,
228 const int>,
229 "SelectVariantType<int, const int, int>::Type should be const int");
230 static_assert(SelectVariantType<int, const int, int>::count == 2,
231 "SelectVariantType<int, const int, int>::count should be 2");
232 static_assert(
233 std::is_same_v<typename SelectVariantType<int, const int, int&&>::Type,
234 const int>,
235 "SelectVariantType<int, const int, int&&>::Type should be const int");
236 static_assert(SelectVariantType<int, const int, int&&>::count == 2,
237 "SelectVariantType<int, const int, int&&>::count should be 2");
240 static void testSimple() {
241 printf("testSimple\n");
242 using V = Variant<uint32_t, uint64_t>;
244 // Non-const lvalue.
245 V v(uint64_t(1));
246 MOZ_RELEASE_ASSERT(v.is<uint64_t>());
247 MOZ_RELEASE_ASSERT(!v.is<uint32_t>());
248 MOZ_RELEASE_ASSERT(v.as<uint64_t>() == 1);
250 MOZ_RELEASE_ASSERT(v.is<1>());
251 MOZ_RELEASE_ASSERT(!v.is<0>());
252 static_assert(std::is_same_v<decltype(v.as<1>()), uint64_t&>,
253 "v.as<1>() should return a uint64_t&");
254 MOZ_RELEASE_ASSERT(v.as<1>() == 1);
256 // Const lvalue.
257 const V& cv = v;
258 MOZ_RELEASE_ASSERT(cv.is<uint64_t>());
259 MOZ_RELEASE_ASSERT(!cv.is<uint32_t>());
260 MOZ_RELEASE_ASSERT(cv.as<uint64_t>() == 1);
262 MOZ_RELEASE_ASSERT(cv.is<1>());
263 MOZ_RELEASE_ASSERT(!cv.is<0>());
264 static_assert(std::is_same_v<decltype(cv.as<1>()), const uint64_t&>,
265 "cv.as<1>() should return a const uint64_t&");
266 MOZ_RELEASE_ASSERT(cv.as<1>() == 1);
268 // Non-const rvalue, using a function to create a temporary.
269 auto MakeV = []() { return V(uint64_t(1)); };
270 MOZ_RELEASE_ASSERT(MakeV().is<uint64_t>());
271 MOZ_RELEASE_ASSERT(!MakeV().is<uint32_t>());
272 MOZ_RELEASE_ASSERT(MakeV().as<uint64_t>() == 1);
274 MOZ_RELEASE_ASSERT(MakeV().is<1>());
275 MOZ_RELEASE_ASSERT(!MakeV().is<0>());
276 static_assert(std::is_same_v<decltype(MakeV().as<1>()), uint64_t&&>,
277 "MakeV().as<1>() should return a uint64_t&&");
278 MOZ_RELEASE_ASSERT(MakeV().as<1>() == 1);
280 // Const rvalue, using a function to create a temporary.
281 auto MakeCV = []() -> const V { return V(uint64_t(1)); };
282 MOZ_RELEASE_ASSERT(MakeCV().is<uint64_t>());
283 MOZ_RELEASE_ASSERT(!MakeCV().is<uint32_t>());
284 MOZ_RELEASE_ASSERT(MakeCV().as<uint64_t>() == 1);
286 MOZ_RELEASE_ASSERT(MakeCV().is<1>());
287 MOZ_RELEASE_ASSERT(!MakeCV().is<0>());
288 static_assert(std::is_same_v<decltype(MakeCV().as<1>()), const uint64_t&&>,
289 "MakeCV().as<1>() should return a const uint64_t&&");
290 MOZ_RELEASE_ASSERT(MakeCV().as<1>() == 1);
293 static void testDuplicate() {
294 printf("testDuplicate\n");
295 Variant<uint32_t, uint64_t, uint32_t> v(uint64_t(1));
296 MOZ_RELEASE_ASSERT(v.is<uint64_t>());
297 MOZ_RELEASE_ASSERT(v.as<uint64_t>() == 1);
298 // Note: uint32_t is not unique, so `v.is<uint32_t>()` is not allowed.
300 MOZ_RELEASE_ASSERT(v.is<1>());
301 MOZ_RELEASE_ASSERT(!v.is<0>());
302 MOZ_RELEASE_ASSERT(!v.is<2>());
303 static_assert(std::is_same_v<decltype(v.as<0>()), uint32_t&>,
304 "as<0>() should return a uint64_t");
305 static_assert(std::is_same_v<decltype(v.as<1>()), uint64_t&>,
306 "as<1>() should return a uint64_t");
307 static_assert(std::is_same_v<decltype(v.as<2>()), uint32_t&>,
308 "as<2>() should return a uint64_t");
309 MOZ_RELEASE_ASSERT(v.as<1>() == 1);
310 MOZ_RELEASE_ASSERT(v.extract<1>() == 1);
313 static void testConstructionWithVariantType() {
314 Variant<uint32_t, uint64_t, uint32_t> v(mozilla::VariantType<uint64_t>{}, 3);
315 MOZ_RELEASE_ASSERT(v.is<uint64_t>());
316 // MOZ_RELEASE_ASSERT(!v.is<uint32_t>()); // uint32_t is not unique!
317 MOZ_RELEASE_ASSERT(v.as<uint64_t>() == 3);
320 static void testConstructionWithVariantIndex() {
321 Variant<uint32_t, uint64_t, uint32_t> v(mozilla::VariantIndex<2>{}, 2);
322 MOZ_RELEASE_ASSERT(!v.is<uint64_t>());
323 // Note: uint32_t is not unique, so `v.is<uint32_t>()` is not allowed.
325 MOZ_RELEASE_ASSERT(!v.is<1>());
326 MOZ_RELEASE_ASSERT(!v.is<0>());
327 MOZ_RELEASE_ASSERT(v.is<2>());
328 MOZ_RELEASE_ASSERT(v.as<2>() == 2);
329 MOZ_RELEASE_ASSERT(v.extract<2>() == 2);
332 static void testEmplaceWithType() {
333 printf("testEmplaceWithType\n");
334 Variant<uint32_t, uint64_t, uint32_t> v1(mozilla::VariantIndex<0>{}, 0);
335 v1.emplace<uint64_t>(3);
336 MOZ_RELEASE_ASSERT(v1.is<uint64_t>());
337 MOZ_RELEASE_ASSERT(v1.as<uint64_t>() == 3);
339 Variant<UniquePtr<int>, char> v2('a');
340 v2.emplace<UniquePtr<int>>();
341 MOZ_RELEASE_ASSERT(v2.is<UniquePtr<int>>());
342 MOZ_RELEASE_ASSERT(!v2.as<UniquePtr<int>>().get());
344 Variant<UniquePtr<int>, char> v3('a');
345 v3.emplace<UniquePtr<int>>(MakeUnique<int>(4));
346 MOZ_RELEASE_ASSERT(v3.is<UniquePtr<int>>());
347 MOZ_RELEASE_ASSERT(*v3.as<UniquePtr<int>>().get() == 4);
350 static void testEmplaceWithIndex() {
351 printf("testEmplaceWithIndex\n");
352 Variant<uint32_t, uint64_t, uint32_t> v1(mozilla::VariantIndex<1>{}, 0);
353 v1.emplace<2>(2);
354 MOZ_RELEASE_ASSERT(!v1.is<uint64_t>());
355 MOZ_RELEASE_ASSERT(!v1.is<1>());
356 MOZ_RELEASE_ASSERT(!v1.is<0>());
357 MOZ_RELEASE_ASSERT(v1.is<2>());
358 MOZ_RELEASE_ASSERT(v1.as<2>() == 2);
359 MOZ_RELEASE_ASSERT(v1.extract<2>() == 2);
361 Variant<UniquePtr<int>, char> v2('a');
362 v2.emplace<0>();
363 MOZ_RELEASE_ASSERT(v2.is<UniquePtr<int>>());
364 MOZ_RELEASE_ASSERT(!v2.is<1>());
365 MOZ_RELEASE_ASSERT(v2.is<0>());
366 MOZ_RELEASE_ASSERT(!v2.as<0>().get());
367 MOZ_RELEASE_ASSERT(!v2.extract<0>().get());
369 Variant<UniquePtr<int>, char> v3('a');
370 v3.emplace<0>(MakeUnique<int>(4));
371 MOZ_RELEASE_ASSERT(v3.is<UniquePtr<int>>());
372 MOZ_RELEASE_ASSERT(!v3.is<1>());
373 MOZ_RELEASE_ASSERT(v3.is<0>());
374 MOZ_RELEASE_ASSERT(*v3.as<0>().get() == 4);
375 MOZ_RELEASE_ASSERT(*v3.extract<0>().get() == 4);
378 static void testCopy() {
379 printf("testCopy\n");
380 Variant<uint32_t, uint64_t> v1(uint64_t(1));
381 Variant<uint32_t, uint64_t> v2(v1);
382 MOZ_RELEASE_ASSERT(v2.is<uint64_t>());
383 MOZ_RELEASE_ASSERT(!v2.is<uint32_t>());
384 MOZ_RELEASE_ASSERT(v2.as<uint64_t>() == 1);
386 Variant<uint32_t, uint64_t> v3(uint32_t(10));
387 v3 = v2;
388 MOZ_RELEASE_ASSERT(v3.is<uint64_t>());
389 MOZ_RELEASE_ASSERT(v3.as<uint64_t>() == 1);
392 static void testMove() {
393 printf("testMove\n");
394 Variant<UniquePtr<int>, char> v1(MakeUnique<int>(5));
395 Variant<UniquePtr<int>, char> v2(std::move(v1));
397 MOZ_RELEASE_ASSERT(v2.is<UniquePtr<int>>());
398 MOZ_RELEASE_ASSERT(*v2.as<UniquePtr<int>>() == 5);
400 MOZ_RELEASE_ASSERT(v1.is<UniquePtr<int>>());
401 MOZ_RELEASE_ASSERT(v1.as<UniquePtr<int>>() == nullptr);
403 Destroyer::destroyedCount = 0;
405 Variant<char, UniquePtr<Destroyer>> v3(MakeUnique<Destroyer>());
406 Variant<char, UniquePtr<Destroyer>> v4(std::move(v3));
408 Variant<char, UniquePtr<Destroyer>> v5('a');
409 v5 = std::move(v4);
411 auto ptr = v5.extract<UniquePtr<Destroyer>>();
412 MOZ_RELEASE_ASSERT(Destroyer::destroyedCount == 0);
414 MOZ_RELEASE_ASSERT(Destroyer::destroyedCount == 1);
417 static void testDestructor() {
418 printf("testDestructor\n");
419 Destroyer::destroyedCount = 0;
422 Destroyer d;
425 Variant<char, UniquePtr<char[]>, Destroyer> v1(d);
426 MOZ_RELEASE_ASSERT(Destroyer::destroyedCount ==
427 0); // None destroyed yet.
430 MOZ_RELEASE_ASSERT(Destroyer::destroyedCount ==
431 1); // v1's copy of d is destroyed.
434 Variant<char, UniquePtr<char[]>, Destroyer> v2(
435 mozilla::VariantIndex<2>{});
436 v2.emplace<Destroyer>(d);
437 MOZ_RELEASE_ASSERT(Destroyer::destroyedCount ==
438 2); // v2's initial value is destroyed.
441 MOZ_RELEASE_ASSERT(Destroyer::destroyedCount ==
442 3); // v2's second value is destroyed.
445 MOZ_RELEASE_ASSERT(Destroyer::destroyedCount == 4); // d is destroyed.
448 static void testEquality() {
449 printf("testEquality\n");
450 using V = Variant<char, int>;
452 V v0('a');
453 V v1('b');
454 V v2('b');
455 V v3(42);
456 V v4(27);
457 V v5(27);
458 V v6(int('b'));
460 MOZ_RELEASE_ASSERT(v0 != v1);
461 MOZ_RELEASE_ASSERT(v1 == v2);
462 MOZ_RELEASE_ASSERT(v2 != v3);
463 MOZ_RELEASE_ASSERT(v3 != v4);
464 MOZ_RELEASE_ASSERT(v4 == v5);
465 MOZ_RELEASE_ASSERT(v1 != v6);
467 MOZ_RELEASE_ASSERT(v0 == v0);
468 MOZ_RELEASE_ASSERT(v1 == v1);
469 MOZ_RELEASE_ASSERT(v2 == v2);
470 MOZ_RELEASE_ASSERT(v3 == v3);
471 MOZ_RELEASE_ASSERT(v4 == v4);
472 MOZ_RELEASE_ASSERT(v5 == v5);
473 MOZ_RELEASE_ASSERT(v6 == v6);
476 // Matcher that returns a description of how its call-operator was invoked.
477 struct Describer {
478 enum class ParameterSize { NA, U8, U32, U64 };
479 enum class ParameterQualifier {
481 ParamLREF,
482 ParamCLREF,
483 ParamRREF,
484 ParamCRREF
486 enum class ThisQualifier { NA, ThisLREF, ThisCLREF, ThisRREF, ThisCRREF };
488 using Result =
489 std::tuple<ParameterSize, ParameterQualifier, ThisQualifier, uint64_t>;
491 #define RESULT(SIZE, PQUAL, TQUAL, VALUE) \
492 Describer::Result(Describer::ParameterSize::SIZE, \
493 Describer::ParameterQualifier::PQUAL, \
494 Describer::ThisQualifier::TQUAL, VALUE)
496 #define CALL(TYPE, SIZE, PQUAL, TREF, TQUAL) \
497 Result operator()(TYPE aValue) TREF { \
498 return RESULT(SIZE, PQUAL, TQUAL, aValue); \
501 // All combinations of possible call operators:
502 // Every line, the parameter integer type changes.
503 // Every 3 lines, the parameter type changes constness.
504 // Every 6 lines, the parameter changes reference l/r-valueness.
505 // Every 12 lines, the member function qualifier changes constness.
506 // After 24 lines, the member function qualifier changes ref l/r-valueness.
507 CALL(uint8_t&, U8, ParamLREF, &, ThisLREF)
508 CALL(uint32_t&, U32, ParamLREF, &, ThisLREF)
509 CALL(uint64_t&, U64, ParamLREF, &, ThisLREF)
511 CALL(const uint8_t&, U8, ParamCLREF, &, ThisLREF)
512 CALL(const uint32_t&, U32, ParamCLREF, &, ThisLREF)
513 CALL(const uint64_t&, U64, ParamCLREF, &, ThisLREF)
515 CALL(uint8_t&&, U8, ParamRREF, &, ThisLREF)
516 CALL(uint32_t&&, U32, ParamRREF, &, ThisLREF)
517 CALL(uint64_t&&, U64, ParamRREF, &, ThisLREF)
519 CALL(const uint8_t&&, U8, ParamCRREF, &, ThisLREF)
520 CALL(const uint32_t&&, U32, ParamCRREF, &, ThisLREF)
521 CALL(const uint64_t&&, U64, ParamCRREF, &, ThisLREF)
523 CALL(uint8_t&, U8, ParamLREF, const&, ThisCLREF)
524 CALL(uint32_t&, U32, ParamLREF, const&, ThisCLREF)
525 CALL(uint64_t&, U64, ParamLREF, const&, ThisCLREF)
527 CALL(const uint8_t&, U8, ParamCLREF, const&, ThisCLREF)
528 CALL(const uint32_t&, U32, ParamCLREF, const&, ThisCLREF)
529 CALL(const uint64_t&, U64, ParamCLREF, const&, ThisCLREF)
531 CALL(uint8_t&&, U8, ParamRREF, const&, ThisCLREF)
532 CALL(uint32_t&&, U32, ParamRREF, const&, ThisCLREF)
533 CALL(uint64_t&&, U64, ParamRREF, const&, ThisCLREF)
535 CALL(const uint8_t&&, U8, ParamCRREF, const&, ThisCLREF)
536 CALL(const uint32_t&&, U32, ParamCRREF, const&, ThisCLREF)
537 CALL(const uint64_t&&, U64, ParamCRREF, const&, ThisCLREF)
539 CALL(uint8_t&, U8, ParamLREF, &&, ThisRREF)
540 CALL(uint32_t&, U32, ParamLREF, &&, ThisRREF)
541 CALL(uint64_t&, U64, ParamLREF, &&, ThisRREF)
543 CALL(const uint8_t&, U8, ParamCLREF, &&, ThisRREF)
544 CALL(const uint32_t&, U32, ParamCLREF, &&, ThisRREF)
545 CALL(const uint64_t&, U64, ParamCLREF, &&, ThisRREF)
547 CALL(uint8_t&&, U8, ParamRREF, &&, ThisRREF)
548 CALL(uint32_t&&, U32, ParamRREF, &&, ThisRREF)
549 CALL(uint64_t&&, U64, ParamRREF, &&, ThisRREF)
551 CALL(const uint8_t&&, U8, ParamCRREF, &&, ThisRREF)
552 CALL(const uint32_t&&, U32, ParamCRREF, &&, ThisRREF)
553 CALL(const uint64_t&&, U64, ParamCRREF, &&, ThisRREF)
555 CALL(uint8_t&, U8, ParamLREF, const&&, ThisCRREF)
556 CALL(uint32_t&, U32, ParamLREF, const&&, ThisCRREF)
557 CALL(uint64_t&, U64, ParamLREF, const&&, ThisCRREF)
559 CALL(const uint8_t&, U8, ParamCLREF, const&&, ThisCRREF)
560 CALL(const uint32_t&, U32, ParamCLREF, const&&, ThisCRREF)
561 CALL(const uint64_t&, U64, ParamCLREF, const&&, ThisCRREF)
563 CALL(uint8_t&&, U8, ParamRREF, const&&, ThisCRREF)
564 CALL(uint32_t&&, U32, ParamRREF, const&&, ThisCRREF)
565 CALL(uint64_t&&, U64, ParamRREF, const&&, ThisCRREF)
567 CALL(const uint8_t&&, U8, ParamCRREF, const&&, ThisCRREF)
568 CALL(const uint32_t&&, U32, ParamCRREF, const&&, ThisCRREF)
569 CALL(const uint64_t&&, U64, ParamCRREF, const&&, ThisCRREF)
571 #undef CALL
573 // Catch-all, to verify that there is no call with any type other than the
574 // expected ones above.
575 template <typename Other>
576 Result operator()(const Other&) {
577 MOZ_RELEASE_ASSERT(false);
578 return RESULT(NA, NA, NA, 0);
582 static void testMatching() {
583 printf("testMatching\n");
584 using V = Variant<uint8_t, uint32_t, uint64_t>;
586 Describer desc;
587 const Describer descConst;
588 auto MakeDescriber = []() { return Describer(); };
589 auto MakeConstDescriber = []() -> const Describer { return Describer(); };
591 V v1(uint8_t(1));
592 V v2(uint32_t(2));
593 V v3(uint64_t(3));
595 const V& constRef1 = v1;
596 const V& constRef2 = v2;
597 const V& constRef3 = v3;
599 // Create a temporary variant by returning a copy of one.
600 auto CopyV = [](const V& aV) { return aV; };
602 // Create a temporary variant by returning a const copy of one.
603 auto CopyConstV = [](const V& aV) -> const V { return aV; };
605 // All combinations of possible calls:
606 // Every line, the variant integer type changes.
607 // Every 3 lines, the variant type changes constness.
608 // Every 6 lines, the variant changes reference l/r-valueness.
609 // Every 12 lines, the matcher changes constness.
610 // After 24 lines, the matcher changes ref l/r-valueness.
611 MOZ_RELEASE_ASSERT(v1.match(desc) == RESULT(U8, ParamLREF, ThisLREF, 1));
612 MOZ_RELEASE_ASSERT(v2.match(desc) == RESULT(U32, ParamLREF, ThisLREF, 2));
613 MOZ_RELEASE_ASSERT(v3.match(desc) == RESULT(U64, ParamLREF, ThisLREF, 3));
615 MOZ_RELEASE_ASSERT(constRef1.match(desc) ==
616 RESULT(U8, ParamCLREF, ThisLREF, 1));
617 MOZ_RELEASE_ASSERT(constRef2.match(desc) ==
618 RESULT(U32, ParamCLREF, ThisLREF, 2));
619 MOZ_RELEASE_ASSERT(constRef3.match(desc) ==
620 RESULT(U64, ParamCLREF, ThisLREF, 3));
622 MOZ_RELEASE_ASSERT(CopyV(v1).match(desc) ==
623 RESULT(U8, ParamRREF, ThisLREF, 1));
624 MOZ_RELEASE_ASSERT(CopyV(v2).match(desc) ==
625 RESULT(U32, ParamRREF, ThisLREF, 2));
626 MOZ_RELEASE_ASSERT(CopyV(v3).match(desc) ==
627 RESULT(U64, ParamRREF, ThisLREF, 3));
629 MOZ_RELEASE_ASSERT(CopyConstV(v1).match(desc) ==
630 RESULT(U8, ParamCRREF, ThisLREF, 1));
631 MOZ_RELEASE_ASSERT(CopyConstV(v2).match(desc) ==
632 RESULT(U32, ParamCRREF, ThisLREF, 2));
633 MOZ_RELEASE_ASSERT(CopyConstV(v3).match(desc) ==
634 RESULT(U64, ParamCRREF, ThisLREF, 3));
636 MOZ_RELEASE_ASSERT(v1.match(descConst) ==
637 RESULT(U8, ParamLREF, ThisCLREF, 1));
638 MOZ_RELEASE_ASSERT(v2.match(descConst) ==
639 RESULT(U32, ParamLREF, ThisCLREF, 2));
640 MOZ_RELEASE_ASSERT(v3.match(descConst) ==
641 RESULT(U64, ParamLREF, ThisCLREF, 3));
643 MOZ_RELEASE_ASSERT(constRef1.match(descConst) ==
644 RESULT(U8, ParamCLREF, ThisCLREF, 1));
645 MOZ_RELEASE_ASSERT(constRef2.match(descConst) ==
646 RESULT(U32, ParamCLREF, ThisCLREF, 2));
647 MOZ_RELEASE_ASSERT(constRef3.match(descConst) ==
648 RESULT(U64, ParamCLREF, ThisCLREF, 3));
650 MOZ_RELEASE_ASSERT(CopyV(v1).match(descConst) ==
651 RESULT(U8, ParamRREF, ThisCLREF, 1));
652 MOZ_RELEASE_ASSERT(CopyV(v2).match(descConst) ==
653 RESULT(U32, ParamRREF, ThisCLREF, 2));
654 MOZ_RELEASE_ASSERT(CopyV(v3).match(descConst) ==
655 RESULT(U64, ParamRREF, ThisCLREF, 3));
657 MOZ_RELEASE_ASSERT(CopyConstV(v1).match(descConst) ==
658 RESULT(U8, ParamCRREF, ThisCLREF, 1));
659 MOZ_RELEASE_ASSERT(CopyConstV(v2).match(descConst) ==
660 RESULT(U32, ParamCRREF, ThisCLREF, 2));
661 MOZ_RELEASE_ASSERT(CopyConstV(v3).match(descConst) ==
662 RESULT(U64, ParamCRREF, ThisCLREF, 3));
664 MOZ_RELEASE_ASSERT(v1.match(MakeDescriber()) ==
665 RESULT(U8, ParamLREF, ThisRREF, 1));
666 MOZ_RELEASE_ASSERT(v2.match(MakeDescriber()) ==
667 RESULT(U32, ParamLREF, ThisRREF, 2));
668 MOZ_RELEASE_ASSERT(v3.match(MakeDescriber()) ==
669 RESULT(U64, ParamLREF, ThisRREF, 3));
671 MOZ_RELEASE_ASSERT(constRef1.match(MakeDescriber()) ==
672 RESULT(U8, ParamCLREF, ThisRREF, 1));
673 MOZ_RELEASE_ASSERT(constRef2.match(MakeDescriber()) ==
674 RESULT(U32, ParamCLREF, ThisRREF, 2));
675 MOZ_RELEASE_ASSERT(constRef3.match(MakeDescriber()) ==
676 RESULT(U64, ParamCLREF, ThisRREF, 3));
678 MOZ_RELEASE_ASSERT(CopyV(v1).match(MakeDescriber()) ==
679 RESULT(U8, ParamRREF, ThisRREF, 1));
680 MOZ_RELEASE_ASSERT(CopyV(v2).match(MakeDescriber()) ==
681 RESULT(U32, ParamRREF, ThisRREF, 2));
682 MOZ_RELEASE_ASSERT(CopyV(v3).match(MakeDescriber()) ==
683 RESULT(U64, ParamRREF, ThisRREF, 3));
685 MOZ_RELEASE_ASSERT(CopyConstV(v1).match(MakeDescriber()) ==
686 RESULT(U8, ParamCRREF, ThisRREF, 1));
687 MOZ_RELEASE_ASSERT(CopyConstV(v2).match(MakeDescriber()) ==
688 RESULT(U32, ParamCRREF, ThisRREF, 2));
689 MOZ_RELEASE_ASSERT(CopyConstV(v3).match(MakeDescriber()) ==
690 RESULT(U64, ParamCRREF, ThisRREF, 3));
692 MOZ_RELEASE_ASSERT(v1.match(MakeConstDescriber()) ==
693 RESULT(U8, ParamLREF, ThisCRREF, 1));
694 MOZ_RELEASE_ASSERT(v2.match(MakeConstDescriber()) ==
695 RESULT(U32, ParamLREF, ThisCRREF, 2));
696 MOZ_RELEASE_ASSERT(v3.match(MakeConstDescriber()) ==
697 RESULT(U64, ParamLREF, ThisCRREF, 3));
699 MOZ_RELEASE_ASSERT(constRef1.match(MakeConstDescriber()) ==
700 RESULT(U8, ParamCLREF, ThisCRREF, 1));
701 MOZ_RELEASE_ASSERT(constRef2.match(MakeConstDescriber()) ==
702 RESULT(U32, ParamCLREF, ThisCRREF, 2));
703 MOZ_RELEASE_ASSERT(constRef3.match(MakeConstDescriber()) ==
704 RESULT(U64, ParamCLREF, ThisCRREF, 3));
706 MOZ_RELEASE_ASSERT(CopyV(v1).match(MakeConstDescriber()) ==
707 RESULT(U8, ParamRREF, ThisCRREF, 1));
708 MOZ_RELEASE_ASSERT(CopyV(v2).match(MakeConstDescriber()) ==
709 RESULT(U32, ParamRREF, ThisCRREF, 2));
710 MOZ_RELEASE_ASSERT(CopyV(v3).match(MakeConstDescriber()) ==
711 RESULT(U64, ParamRREF, ThisCRREF, 3));
713 MOZ_RELEASE_ASSERT(CopyConstV(v1).match(MakeConstDescriber()) ==
714 RESULT(U8, ParamCRREF, ThisCRREF, 1));
715 MOZ_RELEASE_ASSERT(CopyConstV(v2).match(MakeConstDescriber()) ==
716 RESULT(U32, ParamCRREF, ThisCRREF, 2));
717 MOZ_RELEASE_ASSERT(CopyConstV(v3).match(MakeConstDescriber()) ==
718 RESULT(U64, ParamCRREF, ThisCRREF, 3));
721 static void testMatchingLambda() {
722 printf("testMatchingLambda\n");
723 using V = Variant<uint8_t, uint32_t, uint64_t>;
725 // Note: Lambdas' call operators are const by default (unless the lambda is
726 // declared `mutable`).
727 // There is no need to test mutable lambdas, nor rvalue lambda, because there
728 // would be no way to distinguish how each lambda is actually invoked because
729 // there is only one choice of call operator in each overload set.
730 auto desc = [](auto&& a) {
731 if constexpr (std::is_same_v<decltype(a), uint8_t&>) {
732 return RESULT(U8, ParamLREF, NA, a);
733 } else if constexpr (std::is_same_v<decltype(a), const uint8_t&>) {
734 return RESULT(U8, ParamCLREF, NA, a);
735 } else if constexpr (std::is_same_v<decltype(a), uint8_t&&>) {
736 return RESULT(U8, ParamRREF, NA, a);
737 } else if constexpr (std::is_same_v<decltype(a), const uint8_t&&>) {
738 return RESULT(U8, ParamCRREF, NA, a);
739 } else if constexpr (std::is_same_v<decltype(a), uint32_t&>) {
740 return RESULT(U32, ParamLREF, NA, a);
741 } else if constexpr (std::is_same_v<decltype(a), const uint32_t&>) {
742 return RESULT(U32, ParamCLREF, NA, a);
743 } else if constexpr (std::is_same_v<decltype(a), uint32_t&&>) {
744 return RESULT(U32, ParamRREF, NA, a);
745 } else if constexpr (std::is_same_v<decltype(a), const uint32_t&&>) {
746 return RESULT(U32, ParamCRREF, NA, a);
747 } else if constexpr (std::is_same_v<decltype(a), uint64_t&>) {
748 return RESULT(U64, ParamLREF, NA, a);
749 } else if constexpr (std::is_same_v<decltype(a), const uint64_t&>) {
750 return RESULT(U64, ParamCLREF, NA, a);
751 } else if constexpr (std::is_same_v<decltype(a), uint64_t&&>) {
752 return RESULT(U64, ParamRREF, NA, a);
753 } else if constexpr (std::is_same_v<decltype(a), const uint64_t&&>) {
754 return RESULT(U64, ParamCRREF, NA, a);
755 } else {
756 // We don't expect any other type.
757 // Tech note: We can't just do `static_assert(false)` which would always
758 // fail during the initial parsing. So we depend on the templated
759 // parameter to delay computing `false` until actual instantiation.
760 static_assert(sizeof(a) == size_t(-1));
761 return RESULT(NA, NA, NA, 0);
765 V v1(uint8_t(1));
766 V v2(uint32_t(2));
767 V v3(uint64_t(3));
769 const V& constRef1 = v1;
770 const V& constRef2 = v2;
771 const V& constRef3 = v3;
773 // Create a temporary variant by returning a copy of one.
774 auto CopyV = [](const V& aV) { return aV; };
776 // Create a temporary variant by returning a const copy of one.
777 auto CopyConstV = [](const V& aV) -> const V { return aV; };
779 MOZ_RELEASE_ASSERT(v1.match(desc) == RESULT(U8, ParamLREF, NA, 1));
780 MOZ_RELEASE_ASSERT(v2.match(desc) == RESULT(U32, ParamLREF, NA, 2));
781 MOZ_RELEASE_ASSERT(v3.match(desc) == RESULT(U64, ParamLREF, NA, 3));
783 MOZ_RELEASE_ASSERT(constRef1.match(desc) == RESULT(U8, ParamCLREF, NA, 1));
784 MOZ_RELEASE_ASSERT(constRef2.match(desc) == RESULT(U32, ParamCLREF, NA, 2));
785 MOZ_RELEASE_ASSERT(constRef3.match(desc) == RESULT(U64, ParamCLREF, NA, 3));
787 MOZ_RELEASE_ASSERT(CopyV(v1).match(desc) == RESULT(U8, ParamRREF, NA, 1));
788 MOZ_RELEASE_ASSERT(CopyV(v2).match(desc) == RESULT(U32, ParamRREF, NA, 2));
789 MOZ_RELEASE_ASSERT(CopyV(v3).match(desc) == RESULT(U64, ParamRREF, NA, 3));
791 MOZ_RELEASE_ASSERT(CopyConstV(v1).match(desc) ==
792 RESULT(U8, ParamCRREF, NA, 1));
793 MOZ_RELEASE_ASSERT(CopyConstV(v2).match(desc) ==
794 RESULT(U32, ParamCRREF, NA, 2));
795 MOZ_RELEASE_ASSERT(CopyConstV(v3).match(desc) ==
796 RESULT(U64, ParamCRREF, NA, 3));
799 static void testMatchingLambdaWithIndex() {
800 printf("testMatchingLambdaWithIndex\n");
801 using V = Variant<uint8_t, uint32_t, uint64_t>;
803 // Note: Lambdas' call operators are const by default (unless the lambda is
804 // declared `mutable`), hence the use of "...Const" strings below.
805 // There is no need to test mutable lambdas, nor rvalue lambda, because there
806 // would be no way to distinguish how each lambda is actually invoked because
807 // there is only one choice of call operator in each overload set.
808 auto desc = [](auto aIndex, auto&& a) {
809 static_assert(
810 std::is_same_v<decltype(aIndex), uint_fast8_t>,
811 "Expected a uint_fast8_t index for a Variant with 3 alternatives");
812 if constexpr (std::is_same_v<decltype(a), uint8_t&>) {
813 MOZ_RELEASE_ASSERT(aIndex == 0);
814 return RESULT(U8, ParamLREF, NA, a);
815 } else if constexpr (std::is_same_v<decltype(a), const uint8_t&>) {
816 MOZ_RELEASE_ASSERT(aIndex == 0);
817 return RESULT(U8, ParamCLREF, NA, a);
818 } else if constexpr (std::is_same_v<decltype(a), uint8_t&&>) {
819 MOZ_RELEASE_ASSERT(aIndex == 0);
820 return RESULT(U8, ParamRREF, NA, a);
821 } else if constexpr (std::is_same_v<decltype(a), const uint8_t&&>) {
822 MOZ_RELEASE_ASSERT(aIndex == 0);
823 return RESULT(U8, ParamCRREF, NA, a);
824 } else if constexpr (std::is_same_v<decltype(a), uint32_t&>) {
825 MOZ_RELEASE_ASSERT(aIndex == 1);
826 return RESULT(U32, ParamLREF, NA, a);
827 } else if constexpr (std::is_same_v<decltype(a), const uint32_t&>) {
828 MOZ_RELEASE_ASSERT(aIndex == 1);
829 return RESULT(U32, ParamCLREF, NA, a);
830 } else if constexpr (std::is_same_v<decltype(a), uint32_t&&>) {
831 MOZ_RELEASE_ASSERT(aIndex == 1);
832 return RESULT(U32, ParamRREF, NA, a);
833 } else if constexpr (std::is_same_v<decltype(a), const uint32_t&&>) {
834 MOZ_RELEASE_ASSERT(aIndex == 1);
835 return RESULT(U32, ParamCRREF, NA, a);
836 } else if constexpr (std::is_same_v<decltype(a), uint64_t&>) {
837 MOZ_RELEASE_ASSERT(aIndex == 2);
838 return RESULT(U64, ParamLREF, NA, a);
839 } else if constexpr (std::is_same_v<decltype(a), const uint64_t&>) {
840 MOZ_RELEASE_ASSERT(aIndex == 2);
841 return RESULT(U64, ParamCLREF, NA, a);
842 } else if constexpr (std::is_same_v<decltype(a), uint64_t&&>) {
843 MOZ_RELEASE_ASSERT(aIndex == 2);
844 return RESULT(U64, ParamRREF, NA, a);
845 } else if constexpr (std::is_same_v<decltype(a), const uint64_t&&>) {
846 MOZ_RELEASE_ASSERT(aIndex == 2);
847 return RESULT(U64, ParamCRREF, NA, a);
848 } else {
849 // We don't expect any other type.
850 // Tech note: We can't just do `static_assert(false)` which would always
851 // fail during the initial parsing. So we depend on the templated
852 // parameter to delay computing `false` until actual instantiation.
853 static_assert(sizeof(a) == size_t(-1));
854 return RESULT(NA, NA, NA, 0);
858 V v1(uint8_t(1));
859 V v2(uint32_t(2));
860 V v3(uint64_t(3));
862 const V& constRef1 = v1;
863 const V& constRef2 = v2;
864 const V& constRef3 = v3;
866 // Create a temporary variant by returning a copy of one.
867 auto CopyV = [](const V& aV) { return aV; };
869 // Create a temporary variant by returning a const copy of one.
870 auto CopyConstV = [](const V& aV) -> const V { return aV; };
872 MOZ_RELEASE_ASSERT(v1.match(desc) == RESULT(U8, ParamLREF, NA, 1));
873 MOZ_RELEASE_ASSERT(v2.match(desc) == RESULT(U32, ParamLREF, NA, 2));
874 MOZ_RELEASE_ASSERT(v3.match(desc) == RESULT(U64, ParamLREF, NA, 3));
876 MOZ_RELEASE_ASSERT(constRef1.match(desc) == RESULT(U8, ParamCLREF, NA, 1));
877 MOZ_RELEASE_ASSERT(constRef2.match(desc) == RESULT(U32, ParamCLREF, NA, 2));
878 MOZ_RELEASE_ASSERT(constRef3.match(desc) == RESULT(U64, ParamCLREF, NA, 3));
880 MOZ_RELEASE_ASSERT(CopyV(v1).match(desc) == RESULT(U8, ParamRREF, NA, 1));
881 MOZ_RELEASE_ASSERT(CopyV(v2).match(desc) == RESULT(U32, ParamRREF, NA, 2));
882 MOZ_RELEASE_ASSERT(CopyV(v3).match(desc) == RESULT(U64, ParamRREF, NA, 3));
884 MOZ_RELEASE_ASSERT(CopyConstV(v1).match(desc) ==
885 RESULT(U8, ParamCRREF, NA, 1));
886 MOZ_RELEASE_ASSERT(CopyConstV(v2).match(desc) ==
887 RESULT(U32, ParamCRREF, NA, 2));
888 MOZ_RELEASE_ASSERT(CopyConstV(v3).match(desc) ==
889 RESULT(U64, ParamCRREF, NA, 3));
892 static void testMatchingLambdas() {
893 printf("testMatchingLambdas\n");
894 using V = Variant<uint8_t, uint32_t, uint64_t>;
896 auto desc8 = [](auto&& a) {
897 if constexpr (std::is_same_v<decltype(a), uint8_t&>) {
898 return RESULT(U8, ParamLREF, NA, a);
899 } else if constexpr (std::is_same_v<decltype(a), const uint8_t&>) {
900 return RESULT(U8, ParamCLREF, NA, a);
901 } else if constexpr (std::is_same_v<decltype(a), uint8_t&&>) {
902 return RESULT(U8, ParamRREF, NA, a);
903 } else if constexpr (std::is_same_v<decltype(a), const uint8_t&&>) {
904 return RESULT(U8, ParamCRREF, NA, a);
905 } else {
906 // We don't expect any other type.
907 // Tech note: We can't just do `static_assert(false)` which would always
908 // fail during the initial parsing. So we depend on the templated
909 // parameter to delay computing `false` until actual instantiation.
910 static_assert(sizeof(a) == size_t(-1));
911 return RESULT(NA, NA, NA, 0);
914 auto desc32 = [](auto&& a) {
915 if constexpr (std::is_same_v<decltype(a), uint32_t&>) {
916 return RESULT(U32, ParamLREF, NA, a);
917 } else if constexpr (std::is_same_v<decltype(a), const uint32_t&>) {
918 return RESULT(U32, ParamCLREF, NA, a);
919 } else if constexpr (std::is_same_v<decltype(a), uint32_t&&>) {
920 return RESULT(U32, ParamRREF, NA, a);
921 } else if constexpr (std::is_same_v<decltype(a), const uint32_t&&>) {
922 return RESULT(U32, ParamCRREF, NA, a);
923 } else {
924 // We don't expect any other type.
925 // Tech note: We can't just do `static_assert(false)` which would always
926 // fail during the initial parsing. So we depend on the templated
927 // parameter to delay computing `false` until actual instantiation.
928 static_assert(sizeof(a) == size_t(-1));
929 return RESULT(NA, NA, NA, 0);
932 auto desc64 = [](auto&& a) {
933 if constexpr (std::is_same_v<decltype(a), uint64_t&>) {
934 return RESULT(U64, ParamLREF, NA, a);
935 } else if constexpr (std::is_same_v<decltype(a), const uint64_t&>) {
936 return RESULT(U64, ParamCLREF, NA, a);
937 } else if constexpr (std::is_same_v<decltype(a), uint64_t&&>) {
938 return RESULT(U64, ParamRREF, NA, a);
939 } else if constexpr (std::is_same_v<decltype(a), const uint64_t&&>) {
940 return RESULT(U64, ParamCRREF, NA, a);
941 } else {
942 // We don't expect any other type.
943 // Tech note: We can't just do `static_assert(false)` which would always
944 // fail during the initial parsing. So we depend on the templated
945 // parameter to delay computing `false` until actual instantiation.
946 static_assert(sizeof(a) == size_t(-1));
947 return RESULT(NA, NA, NA, 0);
951 V v1(uint8_t(1));
952 V v2(uint32_t(2));
953 V v3(uint64_t(3));
955 const V& constRef1 = v1;
956 const V& constRef2 = v2;
957 const V& constRef3 = v3;
959 // Create a temporary variant by returning a copy of one.
960 auto CopyV = [](const V& aV) { return aV; };
962 // Create a temporary variant by returning a const copy of one.
963 auto CopyConstV = [](const V& aV) -> const V { return aV; };
965 MOZ_RELEASE_ASSERT(v1.match(desc8, desc32, desc64) ==
966 RESULT(U8, ParamLREF, NA, 1));
967 MOZ_RELEASE_ASSERT(v2.match(desc8, desc32, desc64) ==
968 RESULT(U32, ParamLREF, NA, 2));
969 MOZ_RELEASE_ASSERT(v3.match(desc8, desc32, desc64) ==
970 RESULT(U64, ParamLREF, NA, 3));
972 MOZ_RELEASE_ASSERT(constRef1.match(desc8, desc32, desc64) ==
973 RESULT(U8, ParamCLREF, NA, 1));
974 MOZ_RELEASE_ASSERT(constRef2.match(desc8, desc32, desc64) ==
975 RESULT(U32, ParamCLREF, NA, 2));
976 MOZ_RELEASE_ASSERT(constRef3.match(desc8, desc32, desc64) ==
977 RESULT(U64, ParamCLREF, NA, 3));
979 MOZ_RELEASE_ASSERT(CopyV(v1).match(desc8, desc32, desc64) ==
980 RESULT(U8, ParamRREF, NA, 1));
981 MOZ_RELEASE_ASSERT(CopyV(v2).match(desc8, desc32, desc64) ==
982 RESULT(U32, ParamRREF, NA, 2));
983 MOZ_RELEASE_ASSERT(CopyV(v3).match(desc8, desc32, desc64) ==
984 RESULT(U64, ParamRREF, NA, 3));
986 MOZ_RELEASE_ASSERT(CopyConstV(v1).match(desc8, desc32, desc64) ==
987 RESULT(U8, ParamCRREF, NA, 1));
988 MOZ_RELEASE_ASSERT(CopyConstV(v2).match(desc8, desc32, desc64) ==
989 RESULT(U32, ParamCRREF, NA, 2));
990 MOZ_RELEASE_ASSERT(CopyConstV(v3).match(desc8, desc32, desc64) ==
991 RESULT(U64, ParamCRREF, NA, 3));
994 static void testMatchingLambdasWithIndex() {
995 printf("testMatchingLambdasWithIndex\n");
996 using V = Variant<uint8_t, uint32_t, uint64_t>;
998 auto desc8 = [](size_t aIndex, auto&& a) {
999 MOZ_RELEASE_ASSERT(aIndex == 0);
1000 if constexpr (std::is_same_v<decltype(a), uint8_t&>) {
1001 return RESULT(U8, ParamLREF, NA, a);
1002 } else if constexpr (std::is_same_v<decltype(a), const uint8_t&>) {
1003 return RESULT(U8, ParamCLREF, NA, a);
1004 } else if constexpr (std::is_same_v<decltype(a), uint8_t&&>) {
1005 return RESULT(U8, ParamRREF, NA, a);
1006 } else if constexpr (std::is_same_v<decltype(a), const uint8_t&&>) {
1007 return RESULT(U8, ParamCRREF, NA, a);
1008 } else {
1009 // We don't expect any other type.
1010 // Tech note: We can't just do `static_assert(false)` which would always
1011 // fail during the initial parsing. So we depend on the templated
1012 // parameter to delay computing `false` until actual instantiation.
1013 static_assert(sizeof(a) == size_t(-1));
1014 return RESULT(NA, NA, NA, 0);
1017 auto desc32 = [](size_t aIndex, auto&& a) {
1018 MOZ_RELEASE_ASSERT(aIndex == 1);
1019 if constexpr (std::is_same_v<decltype(a), uint32_t&>) {
1020 return RESULT(U32, ParamLREF, NA, a);
1021 } else if constexpr (std::is_same_v<decltype(a), const uint32_t&>) {
1022 return RESULT(U32, ParamCLREF, NA, a);
1023 } else if constexpr (std::is_same_v<decltype(a), uint32_t&&>) {
1024 return RESULT(U32, ParamRREF, NA, a);
1025 } else if constexpr (std::is_same_v<decltype(a), const uint32_t&&>) {
1026 return RESULT(U32, ParamCRREF, NA, a);
1027 } else {
1028 // We don't expect any other type.
1029 // Tech note: We can't just do `static_assert(false)` which would always
1030 // fail during the initial parsing. So we depend on the templated
1031 // parameter to delay computing `false` until actual instantiation.
1032 static_assert(sizeof(a) == size_t(-1));
1033 return RESULT(NA, NA, NA, 0);
1036 auto desc64 = [](size_t aIndex, auto&& a) {
1037 MOZ_RELEASE_ASSERT(aIndex == 2);
1038 if constexpr (std::is_same_v<decltype(a), uint64_t&>) {
1039 return RESULT(U64, ParamLREF, NA, a);
1040 } else if constexpr (std::is_same_v<decltype(a), const uint64_t&>) {
1041 return RESULT(U64, ParamCLREF, NA, a);
1042 } else if constexpr (std::is_same_v<decltype(a), uint64_t&&>) {
1043 return RESULT(U64, ParamRREF, NA, a);
1044 } else if constexpr (std::is_same_v<decltype(a), const uint64_t&&>) {
1045 return RESULT(U64, ParamCRREF, NA, a);
1046 } else {
1047 // We don't expect any other type.
1048 // Tech note: We can't just do `static_assert(false)` which would always
1049 // fail during the initial parsing. So we depend on the templated
1050 // parameter to delay computing `false` until actual instantiation.
1051 static_assert(sizeof(a) == size_t(-1));
1052 return RESULT(NA, NA, NA, 0);
1056 V v1(uint8_t(1));
1057 V v2(uint32_t(2));
1058 V v3(uint64_t(3));
1060 const V& constRef1 = v1;
1061 const V& constRef2 = v2;
1062 const V& constRef3 = v3;
1064 // Create a temporary variant by returning a copy of one.
1065 auto CopyV = [](const V& aV) { return aV; };
1067 // Create a temporary variant by returning a const copy of one.
1068 auto CopyConstV = [](const V& aV) -> const V { return aV; };
1070 MOZ_RELEASE_ASSERT(v1.match(desc8, desc32, desc64) ==
1071 RESULT(U8, ParamLREF, NA, 1));
1072 MOZ_RELEASE_ASSERT(v2.match(desc8, desc32, desc64) ==
1073 RESULT(U32, ParamLREF, NA, 2));
1074 MOZ_RELEASE_ASSERT(v3.match(desc8, desc32, desc64) ==
1075 RESULT(U64, ParamLREF, NA, 3));
1077 MOZ_RELEASE_ASSERT(constRef1.match(desc8, desc32, desc64) ==
1078 RESULT(U8, ParamCLREF, NA, 1));
1079 MOZ_RELEASE_ASSERT(constRef2.match(desc8, desc32, desc64) ==
1080 RESULT(U32, ParamCLREF, NA, 2));
1081 MOZ_RELEASE_ASSERT(constRef3.match(desc8, desc32, desc64) ==
1082 RESULT(U64, ParamCLREF, NA, 3));
1084 MOZ_RELEASE_ASSERT(CopyV(v1).match(desc8, desc32, desc64) ==
1085 RESULT(U8, ParamRREF, NA, 1));
1086 MOZ_RELEASE_ASSERT(CopyV(v2).match(desc8, desc32, desc64) ==
1087 RESULT(U32, ParamRREF, NA, 2));
1088 MOZ_RELEASE_ASSERT(CopyV(v3).match(desc8, desc32, desc64) ==
1089 RESULT(U64, ParamRREF, NA, 3));
1091 MOZ_RELEASE_ASSERT(CopyConstV(v1).match(desc8, desc32, desc64) ==
1092 RESULT(U8, ParamCRREF, NA, 1));
1093 MOZ_RELEASE_ASSERT(CopyConstV(v2).match(desc8, desc32, desc64) ==
1094 RESULT(U32, ParamCRREF, NA, 2));
1095 MOZ_RELEASE_ASSERT(CopyConstV(v3).match(desc8, desc32, desc64) ==
1096 RESULT(U64, ParamCRREF, NA, 3));
1099 #undef RESULT
1101 static void testAddTagToHash() {
1102 printf("testAddToHash\n");
1103 using V = Variant<uint8_t, uint16_t, uint32_t, uint64_t>;
1105 // We don't know what our hash function is, and these are certainly not all
1106 // true under all hash functions. But they are probably true under almost any
1107 // decent hash function, and our aim is simply to establish that the tag
1108 // *does* influence the hash value.
1110 mozilla::HashNumber h8 = V(uint8_t(1)).addTagToHash(0);
1111 mozilla::HashNumber h16 = V(uint16_t(1)).addTagToHash(0);
1112 mozilla::HashNumber h32 = V(uint32_t(1)).addTagToHash(0);
1113 mozilla::HashNumber h64 = V(uint64_t(1)).addTagToHash(0);
1115 MOZ_RELEASE_ASSERT(h8 != h16 && h8 != h32 && h8 != h64);
1116 MOZ_RELEASE_ASSERT(h16 != h32 && h16 != h64);
1117 MOZ_RELEASE_ASSERT(h32 != h64);
1121 mozilla::HashNumber h8 = V(uint8_t(1)).addTagToHash(0x124356);
1122 mozilla::HashNumber h16 = V(uint16_t(1)).addTagToHash(0x124356);
1123 mozilla::HashNumber h32 = V(uint32_t(1)).addTagToHash(0x124356);
1124 mozilla::HashNumber h64 = V(uint64_t(1)).addTagToHash(0x124356);
1126 MOZ_RELEASE_ASSERT(h8 != h16 && h8 != h32 && h8 != h64);
1127 MOZ_RELEASE_ASSERT(h16 != h32 && h16 != h64);
1128 MOZ_RELEASE_ASSERT(h32 != h64);
1132 int main() {
1133 testDetails();
1134 testSimple();
1135 testDuplicate();
1136 testConstructionWithVariantType();
1137 testConstructionWithVariantIndex();
1138 testEmplaceWithType();
1139 testEmplaceWithIndex();
1140 testCopy();
1141 testMove();
1142 testDestructor();
1143 testEquality();
1144 testMatching();
1145 testMatchingLambda();
1146 testMatchingLambdaWithIndex();
1147 testMatchingLambdas();
1148 testMatchingLambdasWithIndex();
1149 testAddTagToHash();
1151 printf("TestVariant OK!\n");
1152 return 0;