TestVariant.cpp (47614B)
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/. */ 6 7 #include <type_traits> 8 9 #include "mozilla/UniquePtr.h" 10 #include "mozilla/Variant.h" 11 12 #include <tuple> 13 14 using mozilla::MakeUnique; 15 using mozilla::UniquePtr; 16 using mozilla::Variant; 17 18 struct Destroyer { 19 static int destroyedCount; 20 ~Destroyer() { destroyedCount++; } 21 }; 22 23 int Destroyer::destroyedCount = 0; 24 25 static void testDetails() { 26 printf("testDetails\n"); 27 28 using mozilla::detail::Nth; 29 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"); 33 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"); 39 40 using mozilla::detail::SelectVariantType; 41 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"); 46 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"); 54 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"); 61 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"); 69 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"); 76 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"); 83 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"); 91 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"); 99 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"); 106 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"); 113 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"); 121 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"); 129 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"); 137 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"); 144 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"); 152 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"); 160 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"); 167 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"); 180 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"); 187 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"); 195 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"); 202 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"); 209 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"); 218 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"); 238 } 239 240 static void testSimple() { 241 printf("testSimple\n"); 242 using V = Variant<uint32_t, uint64_t>; 243 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); 249 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); 255 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); 261 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); 267 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); 273 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); 279 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); 285 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); 291 } 292 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. 299 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); 311 } 312 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); 318 } 319 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. 324 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); 330 } 331 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); 338 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()); 343 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); 348 } 349 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); 360 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()); 368 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); 376 } 377 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); 385 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); 390 } 391 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)); 396 397 MOZ_RELEASE_ASSERT(v2.is<UniquePtr<int>>()); 398 MOZ_RELEASE_ASSERT(*v2.as<UniquePtr<int>>() == 5); 399 400 MOZ_RELEASE_ASSERT(v1.is<UniquePtr<int>>()); 401 MOZ_RELEASE_ASSERT(v1.as<UniquePtr<int>>() == nullptr); 402 403 Destroyer::destroyedCount = 0; 404 { 405 Variant<char, UniquePtr<Destroyer>> v3(MakeUnique<Destroyer>()); 406 Variant<char, UniquePtr<Destroyer>> v4(std::move(v3)); 407 408 Variant<char, UniquePtr<Destroyer>> v5('a'); 409 v5 = std::move(v4); 410 411 auto ptr = v5.extract<UniquePtr<Destroyer>>(); 412 MOZ_RELEASE_ASSERT(Destroyer::destroyedCount == 0); 413 } 414 MOZ_RELEASE_ASSERT(Destroyer::destroyedCount == 1); 415 } 416 417 static void testDestructor() { 418 printf("testDestructor\n"); 419 Destroyer::destroyedCount = 0; 420 421 { 422 Destroyer d; 423 424 { 425 Variant<char, UniquePtr<char[]>, Destroyer> v1(d); 426 MOZ_RELEASE_ASSERT(Destroyer::destroyedCount == 427 0); // None destroyed yet. 428 } 429 430 MOZ_RELEASE_ASSERT(Destroyer::destroyedCount == 431 1); // v1's copy of d is destroyed. 432 433 { 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. 439 } 440 441 MOZ_RELEASE_ASSERT(Destroyer::destroyedCount == 442 3); // v2's second value is destroyed. 443 } 444 445 MOZ_RELEASE_ASSERT(Destroyer::destroyedCount == 4); // d is destroyed. 446 } 447 448 static void testEquality() { 449 printf("testEquality\n"); 450 using V = Variant<char, int>; 451 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')); 459 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); 466 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); 474 } 475 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 { 480 NA, 481 ParamLREF, 482 ParamCLREF, 483 ParamRREF, 484 ParamCRREF 485 }; 486 enum class ThisQualifier { NA, ThisLREF, ThisCLREF, ThisRREF, ThisCRREF }; 487 488 using Result = 489 std::tuple<ParameterSize, ParameterQualifier, ThisQualifier, uint64_t>; 490 491 #define RESULT(SIZE, PQUAL, TQUAL, VALUE) \ 492 Describer::Result(Describer::ParameterSize::SIZE, \ 493 Describer::ParameterQualifier::PQUAL, \ 494 Describer::ThisQualifier::TQUAL, VALUE) 495 496 #define CALL(TYPE, SIZE, PQUAL, TREF, TQUAL) \ 497 Result operator()(TYPE aValue) TREF { \ 498 return RESULT(SIZE, PQUAL, TQUAL, aValue); \ 499 } 500 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) 510 511 CALL(const uint8_t&, U8, ParamCLREF, &, ThisLREF) 512 CALL(const uint32_t&, U32, ParamCLREF, &, ThisLREF) 513 CALL(const uint64_t&, U64, ParamCLREF, &, ThisLREF) 514 515 CALL(uint8_t&&, U8, ParamRREF, &, ThisLREF) 516 CALL(uint32_t&&, U32, ParamRREF, &, ThisLREF) 517 CALL(uint64_t&&, U64, ParamRREF, &, ThisLREF) 518 519 CALL(const uint8_t&&, U8, ParamCRREF, &, ThisLREF) 520 CALL(const uint32_t&&, U32, ParamCRREF, &, ThisLREF) 521 CALL(const uint64_t&&, U64, ParamCRREF, &, ThisLREF) 522 523 CALL(uint8_t&, U8, ParamLREF, const&, ThisCLREF) 524 CALL(uint32_t&, U32, ParamLREF, const&, ThisCLREF) 525 CALL(uint64_t&, U64, ParamLREF, const&, ThisCLREF) 526 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) 530 531 CALL(uint8_t&&, U8, ParamRREF, const&, ThisCLREF) 532 CALL(uint32_t&&, U32, ParamRREF, const&, ThisCLREF) 533 CALL(uint64_t&&, U64, ParamRREF, const&, ThisCLREF) 534 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) 538 539 CALL(uint8_t&, U8, ParamLREF, &&, ThisRREF) 540 CALL(uint32_t&, U32, ParamLREF, &&, ThisRREF) 541 CALL(uint64_t&, U64, ParamLREF, &&, ThisRREF) 542 543 CALL(const uint8_t&, U8, ParamCLREF, &&, ThisRREF) 544 CALL(const uint32_t&, U32, ParamCLREF, &&, ThisRREF) 545 CALL(const uint64_t&, U64, ParamCLREF, &&, ThisRREF) 546 547 CALL(uint8_t&&, U8, ParamRREF, &&, ThisRREF) 548 CALL(uint32_t&&, U32, ParamRREF, &&, ThisRREF) 549 CALL(uint64_t&&, U64, ParamRREF, &&, ThisRREF) 550 551 CALL(const uint8_t&&, U8, ParamCRREF, &&, ThisRREF) 552 CALL(const uint32_t&&, U32, ParamCRREF, &&, ThisRREF) 553 CALL(const uint64_t&&, U64, ParamCRREF, &&, ThisRREF) 554 555 CALL(uint8_t&, U8, ParamLREF, const&&, ThisCRREF) 556 CALL(uint32_t&, U32, ParamLREF, const&&, ThisCRREF) 557 CALL(uint64_t&, U64, ParamLREF, const&&, ThisCRREF) 558 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) 562 563 CALL(uint8_t&&, U8, ParamRREF, const&&, ThisCRREF) 564 CALL(uint32_t&&, U32, ParamRREF, const&&, ThisCRREF) 565 CALL(uint64_t&&, U64, ParamRREF, const&&, ThisCRREF) 566 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) 570 571 #undef CALL 572 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); 579 } 580 }; 581 582 static void testMatching() { 583 printf("testMatching\n"); 584 using V = Variant<uint8_t, uint32_t, uint64_t>; 585 586 Describer desc; 587 const Describer descConst; 588 auto MakeDescriber = []() { return Describer(); }; 589 auto MakeConstDescriber = []() -> const Describer { return Describer(); }; 590 591 V v1(uint8_t(1)); 592 V v2(uint32_t(2)); 593 V v3(uint64_t(3)); 594 595 const V& constRef1 = v1; 596 const V& constRef2 = v2; 597 const V& constRef3 = v3; 598 599 // Create a temporary variant by returning a copy of one. 600 auto CopyV = [](const V& aV) { return aV; }; 601 602 // Create a temporary variant by returning a const copy of one. 603 auto CopyConstV = [](const V& aV) -> const V { return aV; }; 604 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)); 614 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)); 621 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)); 628 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)); 635 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)); 642 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)); 649 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)); 656 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)); 663 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)); 670 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)); 677 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)); 684 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)); 691 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)); 698 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)); 705 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)); 712 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)); 719 } 720 721 static void testMatchingLambda() { 722 printf("testMatchingLambda\n"); 723 using V = Variant<uint8_t, uint32_t, uint64_t>; 724 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); 762 } 763 }; 764 765 V v1(uint8_t(1)); 766 V v2(uint32_t(2)); 767 V v3(uint64_t(3)); 768 769 const V& constRef1 = v1; 770 const V& constRef2 = v2; 771 const V& constRef3 = v3; 772 773 // Create a temporary variant by returning a copy of one. 774 auto CopyV = [](const V& aV) { return aV; }; 775 776 // Create a temporary variant by returning a const copy of one. 777 auto CopyConstV = [](const V& aV) -> const V { return aV; }; 778 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)); 782 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)); 786 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)); 790 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)); 797 } 798 799 static void testMatchingLambdaWithIndex() { 800 printf("testMatchingLambdaWithIndex\n"); 801 using V = Variant<uint8_t, uint32_t, uint64_t>; 802 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); 855 } 856 }; 857 858 V v1(uint8_t(1)); 859 V v2(uint32_t(2)); 860 V v3(uint64_t(3)); 861 862 const V& constRef1 = v1; 863 const V& constRef2 = v2; 864 const V& constRef3 = v3; 865 866 // Create a temporary variant by returning a copy of one. 867 auto CopyV = [](const V& aV) { return aV; }; 868 869 // Create a temporary variant by returning a const copy of one. 870 auto CopyConstV = [](const V& aV) -> const V { return aV; }; 871 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)); 875 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)); 879 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)); 883 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)); 890 } 891 892 static void testMatchingLambdas() { 893 printf("testMatchingLambdas\n"); 894 using V = Variant<uint8_t, uint32_t, uint64_t>; 895 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); 912 } 913 }; 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); 930 } 931 }; 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); 948 } 949 }; 950 951 V v1(uint8_t(1)); 952 V v2(uint32_t(2)); 953 V v3(uint64_t(3)); 954 955 const V& constRef1 = v1; 956 const V& constRef2 = v2; 957 const V& constRef3 = v3; 958 959 // Create a temporary variant by returning a copy of one. 960 auto CopyV = [](const V& aV) { return aV; }; 961 962 // Create a temporary variant by returning a const copy of one. 963 auto CopyConstV = [](const V& aV) -> const V { return aV; }; 964 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)); 971 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)); 978 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)); 985 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)); 992 } 993 994 static void testMatchingLambdasWithIndex() { 995 printf("testMatchingLambdasWithIndex\n"); 996 using V = Variant<uint8_t, uint32_t, uint64_t>; 997 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); 1015 } 1016 }; 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); 1034 } 1035 }; 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); 1053 } 1054 }; 1055 1056 V v1(uint8_t(1)); 1057 V v2(uint32_t(2)); 1058 V v3(uint64_t(3)); 1059 1060 const V& constRef1 = v1; 1061 const V& constRef2 = v2; 1062 const V& constRef3 = v3; 1063 1064 // Create a temporary variant by returning a copy of one. 1065 auto CopyV = [](const V& aV) { return aV; }; 1066 1067 // Create a temporary variant by returning a const copy of one. 1068 auto CopyConstV = [](const V& aV) -> const V { return aV; }; 1069 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)); 1076 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)); 1083 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)); 1090 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)); 1097 } 1098 1099 #undef RESULT 1100 1101 static void testAddTagToHash() { 1102 printf("testAddToHash\n"); 1103 using V = Variant<uint8_t, uint16_t, uint32_t, uint64_t>; 1104 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. 1109 { 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); 1114 1115 MOZ_RELEASE_ASSERT(h8 != h16 && h8 != h32 && h8 != h64); 1116 MOZ_RELEASE_ASSERT(h16 != h32 && h16 != h64); 1117 MOZ_RELEASE_ASSERT(h32 != h64); 1118 } 1119 1120 { 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); 1125 1126 MOZ_RELEASE_ASSERT(h8 != h16 && h8 != h32 && h8 != h64); 1127 MOZ_RELEASE_ASSERT(h16 != h32 && h16 != h64); 1128 MOZ_RELEASE_ASSERT(h32 != h64); 1129 } 1130 } 1131 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(); 1150 1151 printf("TestVariant OK!\n"); 1152 return 0; 1153 }