12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include <AzCore/std/containers/variant.h>
- #include "UserTypes.h"
- namespace UnitTest
- {
- //////////////////////////////////////////////////////////////////////////
- // Fixtures
- // Fixture for non-typed tests
- class VariantTest
- : public LeakDetectionFixture
- {
- };
- template<typename TestConfig>
- class VariantSizeTest
- : public LeakDetectionFixture
- {
- };
- template<typename VariantType, size_t ExpectedSize>
- struct VariantSizeTestConfig
- {
- using type = VariantType;
- static constexpr size_t expected_size = ExpectedSize;
- };
- using VariantSizeTestConfigs = ::testing::Types<
- VariantSizeTestConfig<AZStd::variant<AZStd::monostate>, 1>
- , VariantSizeTestConfig<AZStd::variant<void*, const void*>, 2>
- , VariantSizeTestConfig<AZStd::variant<uint64_t, AZStd::string, uint64_t, double>, 4>
- >;
- TYPED_TEST_SUITE(VariantSizeTest, VariantSizeTestConfigs);
- template<typename TestConfig>
- class VariantAlternativeTest
- : public LeakDetectionFixture
- {
- };
- template<typename VariantType, size_t Index, typename AlternativeType>
- struct VariantAlternativeTestConfig
- {
- using type = VariantType;
- using expected_type = AlternativeType;
- static constexpr size_t expected_index = Index;
- };
- using Variant6AltType = AZStd::variant<AZStd::monostate, void*, const void*, double, int32_t, uintptr_t>;
- using VariantAlternativeTestConfigs = ::testing::Types<
- VariantAlternativeTestConfig<Variant6AltType, 0, AZStd::monostate>
- , VariantAlternativeTestConfig<Variant6AltType, 1, void*>
- , VariantAlternativeTestConfig<Variant6AltType, 2, const void*>
- , VariantAlternativeTestConfig<Variant6AltType, 3, double>
- , VariantAlternativeTestConfig<Variant6AltType, 4, int32_t>
- , VariantAlternativeTestConfig<Variant6AltType, 5, uintptr_t>
- >;
- TYPED_TEST_SUITE(VariantAlternativeTest, VariantAlternativeTestConfigs);
- namespace VariantTestInternal
- {
- struct TrivialAlt
- {};
- struct NonDefaultConstructible
- {
- constexpr NonDefaultConstructible(bool)
- {}
- };
- struct MoveConstructorOnly
- {
- MoveConstructorOnly() = default;
- MoveConstructorOnly(const MoveConstructorOnly&) = delete;
- MoveConstructorOnly(MoveConstructorOnly&& other)
- {
- memcpy(m_alignedBuffer, other.m_alignedBuffer, sizeof(m_alignedBuffer));
- memset(other.m_alignedBuffer, 0, sizeof(other.m_alignedBuffer));
- }
- alignas(16) uint8_t m_alignedBuffer[32];
- };
- struct MoveOnly
- {
- MoveOnly() = default;
- MoveOnly(const MoveOnly&) = delete;
- MoveOnly& operator=(const MoveOnly&) = delete;
- MoveOnly(MoveOnly&& other)
- {
- m_value = other.m_value;
- other.m_value = {};
- m_moveConstructed = true;
- }
- MoveOnly& operator=(MoveOnly&& rhs)
- {
- m_value = rhs.m_value;
- rhs.m_value = {};
- ++m_moveAssignmentCounter;
- return *this;
- }
- int32_t m_value{};
- int32_t m_moveAssignmentCounter{};
- bool m_moveConstructed{};
- };
- struct CopyConstructorOnly
- {
- CopyConstructorOnly() = default;
- CopyConstructorOnly(const CopyConstructorOnly& other)
- {
- memcpy(m_alignedBuffer, other.m_alignedBuffer, sizeof(m_alignedBuffer));
- }
- CopyConstructorOnly(CopyConstructorOnly&& other) = delete;
- alignas(16) uint8_t m_alignedBuffer[32];
- };
- struct ConstexprVisitorHelper
- {
- template <typename... Args>
- constexpr int64_t operator()(int64_t numAlt, Args&&...) const
- {
- return numAlt;
- }
- };
- struct VariadicVariantSizeof
- {
- template <typename... Args>
- constexpr size_t operator()(Args&&...) const
- {
- return sizeof...(Args);
- }
- };
- enum class MemberFuncQualifiers : uint32_t
- {
- const_ = 1,
- lvalue_ref = 2,
- rvalue_ref = 4,
- const_lvalue_ref = const_ | lvalue_ref,
- const_rvalue_ref = const_ | rvalue_ref,
- };
- struct MemberFuncQualifierCallable
- {
- template <typename... Args>
- MemberFuncQualifiers operator()(Args&&...) &
- {
- return MemberFuncQualifiers::lvalue_ref;
- }
- template <typename... Args>
- MemberFuncQualifiers operator()(Args&&...) const &
- {
- return MemberFuncQualifiers::const_lvalue_ref;
- }
- template <typename... Args>
- MemberFuncQualifiers operator()(Args&&...) &&
- {
- return MemberFuncQualifiers::rvalue_ref;
- }
- template <typename... Args>
- MemberFuncQualifiers operator()(Args&&...) const &&
- {
- return MemberFuncQualifiers::const_rvalue_ref;
- }
- };
- struct ParameterQualifierCallable
- {
- template <typename... Args>
- MemberFuncQualifiers operator()(Args&&...)
- {
- constexpr bool lvalueArg = AZStd::conjunction<AZStd::is_lvalue_reference<Args>...>::value;
- constexpr bool constArg = AZStd::conjunction<AZStd::is_const<AZStd::remove_reference_t<Args>>...>::value;
- AZ_PUSH_DISABLE_WARNING(4127, "-Wunknown-warning-option") // conditional expression is constant
- if (lvalueArg && !constArg)
- {
- return MemberFuncQualifiers::lvalue_ref;
- }
- else if (lvalueArg && constArg)
- {
- return MemberFuncQualifiers::const_lvalue_ref;
- }
- else if (!lvalueArg && !constArg)
- {
- return MemberFuncQualifiers::rvalue_ref;
- }
- else if (!lvalueArg && constArg)
- {
- return MemberFuncQualifiers::const_rvalue_ref;
- }
- AZ_POP_DISABLE_WARNING
- return MemberFuncQualifiers{};
- }
- };
- template <typename Sequence>
- struct make_heterogeneous_variant;
- template <size_t... Indices>
- struct make_heterogeneous_variant<AZStd::index_sequence<Indices...>>
- {
- template <size_t Index>
- using alternative_t = uint64_t;
- using type = AZStd::variant<alternative_t<Indices>...>;
- };
- template <size_t NumAlternatives>
- using make_heterogeneous_variant_t = typename make_heterogeneous_variant<AZStd::make_index_sequence<NumAlternatives>>::type;
- }
- // variant_size test
- TYPED_TEST(VariantSizeTest, variant_sizeReturnsCorrectSizeWithConstVolatileQualifiers)
- {
- static_assert(TypeParam::expected_size == AZStd::variant_size<typename TypeParam::type>::value, "Variant size is not equal to expected result");
- static_assert(TypeParam::expected_size == AZStd::variant_size<const typename TypeParam::type>::value, "Variant size is not equal to expected result");
- static_assert(TypeParam::expected_size == AZStd::variant_size<volatile typename TypeParam::type>::value, "Variant size is not equal to expected result");
- static_assert(TypeParam::expected_size == AZStd::variant_size<const volatile typename TypeParam::type>::value, "Variant size is not equal to expected result");
- static_assert(TypeParam::expected_size == AZStd::variant_size_v<typename TypeParam::type>, "Variant size is not equal to expected result");
- static_assert(TypeParam::expected_size == AZStd::variant_size_v<const typename TypeParam::type>, "Variant size is not equal to expected result");
- static_assert(TypeParam::expected_size == AZStd::variant_size_v<volatile typename TypeParam::type>, "Variant size is not equal to expected result");
- static_assert(TypeParam::expected_size == AZStd::variant_size_v<const volatile typename TypeParam::type>, "Variant size is not equal to expected result");
- }
- TEST_F(VariantTest, variant_sizeReturnsNumberOfAlternatives)
- {
- using TestVariant1 = AZStd::variant<int, float, bool, AZStd::string_view>;
- static_assert(AZStd::variant_size_v<TestVariant1> == 4, "Variant size should be equal to the number of alternatives");
- using TestVariant2 = AZStd::variant<int, float, bool, AZStd::string, float>;
- static_assert(AZStd::variant_size_v<TestVariant2> == 5, "Variant size should be equal to the number of alternatives");
- }
- // variant_alternative test
- TYPED_TEST(VariantAlternativeTest, variant_alternativeReturnsCorrectTypeForIndex)
- {
- static_assert(AZStd::is_same_v<typename TypeParam::expected_type, typename AZStd::variant_alternative<TypeParam::expected_index, typename TypeParam::type>::type>, "Variant size is not equal to expected result");
- static_assert(AZStd::is_same_v<const typename TypeParam::expected_type, typename AZStd::variant_alternative<TypeParam::expected_index, const typename TypeParam::type>::type>, "Variant size is not equal to expected result");
- static_assert(AZStd::is_same_v<volatile typename TypeParam::expected_type, typename AZStd::variant_alternative<TypeParam::expected_index, volatile typename TypeParam::type>::type>, "Variant size is not equal to expected result");
- static_assert(AZStd::is_same_v<const volatile typename TypeParam::expected_type, typename AZStd::variant_alternative<TypeParam::expected_index, const volatile typename TypeParam::type>::type>, "Variant size is not equal to expected result");
- static_assert(AZStd::is_same_v<typename TypeParam::expected_type, AZStd::variant_alternative_t<TypeParam::expected_index, typename TypeParam::type>>, "Variant size is not equal to expected result");
- static_assert(AZStd::is_same_v<const typename TypeParam::expected_type, AZStd::variant_alternative_t<TypeParam::expected_index, const typename TypeParam::type>>, "Variant size is not equal to expected result");
- static_assert(AZStd::is_same_v<volatile typename TypeParam::expected_type, AZStd::variant_alternative_t<TypeParam::expected_index, volatile typename TypeParam::type>>, "Variant size is not equal to expected result");
- static_assert(AZStd::is_same_v<const volatile typename TypeParam::expected_type, AZStd::variant_alternative_t<TypeParam::expected_index, const volatile typename TypeParam::type>>, "Variant size is not equal to expected result");
- }
- TEST_F(VariantTest, sizeof_VariantIsGreaterThanLargestElementSize)
- {
- // Largest Element is string_view
- using TestVariant1 = AZStd::variant<int, float, bool, AZStd::string_view>;
-
- static_assert(sizeof(AZStd::string_view) < sizeof(TestVariant1), "using the sizeof operator on a std::variant should return a size larger than all the alternatives");
- // Largest Element is MoveOnly
- using TestVariant2 = AZStd::variant<double, AZStd::string_view, VariantTestInternal::MoveConstructorOnly, bool, float>;
- static_assert(sizeof(VariantTestInternal::MoveConstructorOnly) < sizeof(TestVariant2), "using the sizeof operator on a std::variant should return a size larger than all the alternatives");
- }
- TEST_F(VariantTest, sizeof_VariantIsLessThanCombinedAlternativeSize)
- {
- // Largest Element is string_view
- using TestVariant1 = AZStd::variant<int, float, bool, AZStd::string_view, AZStd::string_view>;
- // For a variant with less than 255 alternatives the index type is an uint8_t
- constexpr size_t variantAlignment = alignof(TestVariant1);
- constexpr size_t maxExpectedVariantByteSize = (sizeof(AZStd::string_view) + sizeof(uint8_t) + variantAlignment - 1) & ~(variantAlignment - 1);
- constexpr size_t testVariantByteSize = sizeof(TestVariant1);
- static_assert(testVariantByteSize <= maxExpectedVariantByteSize, "using the sizeof operator on a std::variant should return a size smaller"
- " than the sizeof(largest type) + padding + sizeof(index type)");
- }
- TEST_F(VariantTest, DifferentPermutationsOfVariantHasSameSize)
- {
- constexpr size_t alignedStorageSize = 144;
- using TestAlignedStorage = AZStd::aligned_storage_t<alignedStorageSize, 16>;
- // Largest Element is string_view
- using TestVariant1 = AZStd::variant<int, float, bool, TestAlignedStorage>;
- using TestVariant2 = AZStd::variant<TestAlignedStorage, float, bool, int>;
- static_assert(sizeof(TestVariant1) == sizeof(TestVariant2), "with different permutations variants of same types should be the same size");
- using UnorderedVariant3 = AZStd::variant<AZStd::unordered_map<AZStd::string, AZStd::string>, TestAlignedStorage>;
- static_assert(sizeof(TestVariant1) == sizeof(UnorderedVariant3), "with different permutations variants of same types should be the same size");
- }
- TEST_F(VariantTest, VariantIndexTypeIsLessSizeIfLessThan255Alternatives)
- {
- constexpr size_t indexSizeWithOneAlternatives = sizeof(AZStd::variant_index_t<1>);
- constexpr size_t indexSizeWithOneByteMaxAlternatives = sizeof(AZStd::variant_index_t<std::numeric_limits<uint8_t>::max() - 1>);
- constexpr size_t indexSizeWithTwoByteMinAlternatives = sizeof(AZStd::variant_index_t<std::numeric_limits<uint8_t>::max()>);
- static_assert(indexSizeWithOneAlternatives == indexSizeWithOneByteMaxAlternatives, "the index type for a variant with 1 alternative should be the same size for a variant with 254 alternatives");
- static_assert(indexSizeWithOneByteMaxAlternatives < indexSizeWithTwoByteMinAlternatives, "the index type for a variant with 254 alternatives should be smaller for a variant with 255 alternatives");
- }
- namespace Constructors
- {
- TEST_F(VariantTest, DefaultConstructorVariantSetsIndexZero)
- {
- constexpr AZStd::variant<AZStd::monostate> monostateVariant;
- static_assert(monostateVariant.index() == 0U, "Default Constructed variant should be constructed to first alternative");
- EXPECT_EQ(0U, monostateVariant.index());
- }
- TEST_F(VariantTest, DefaultConstructorSucceedsWhenOnlyFirstAlternativeIsDefaultConstructible)
- {
- AZStd::variant<AZStd::string_view, VariantTestInternal::NonDefaultConstructible> testVariant;
- EXPECT_EQ(0U, testVariant.index());
- EXPECT_TRUE(AZStd::get<0>(testVariant).empty());
- }
- TEST_F(VariantTest, ConvertingConstructorSucceeds)
- {
- const AZStd::variant<AZStd::string> stringVariant{ AZStd::string("Test String") };
- const AZStd::variant<AZStd::string> convertToStringVariant{ "Test String" };
- EXPECT_EQ(stringVariant, convertToStringVariant);
- }
- TEST_F(VariantTest, CopyConstructorSucceeds)
- {
- AZStd::variant<uint32_t, AZStd::string> numberStringUnion{ 5U };
- AZStd::variant<uint32_t, AZStd::string> copiedUnion(numberStringUnion);
- EXPECT_EQ(copiedUnion, numberStringUnion);
- const AZStd::variant<AZStd::string, int32_t> testVariant3{ AZStd::in_place_index_t<1>{}, 6 };
- const AZStd::variant<AZStd::string, int32_t > copyVariant(testVariant3);
- EXPECT_EQ(testVariant3, copyVariant);
- ASSERT_EQ(1, copyVariant.index());
- EXPECT_EQ(6, AZStd::get<1>(copyVariant));
- }
- TEST_F(VariantTest, MoveConstructorSucceeds)
- {
- AZStd::variant<AZStd::string> sourceStringUnion("Hello World");
- AZStd::variant<AZStd::string> moveUnion(AZStd::move(sourceStringUnion));
- EXPECT_NE(moveUnion, sourceStringUnion);
- // Moved from Variant should have default value
- EXPECT_TRUE(AZStd::get<0>(sourceStringUnion).empty());
- AZStd::variant<AZStd::string, AZStd::string_view> testVariant3{ AZStd::in_place_index_t<1>{}, "Hello" };
- AZStd::variant<AZStd::string, AZStd::string_view > moveVariant(AZStd::move(testVariant3));
- EXPECT_NE(testVariant3, moveVariant);
- ASSERT_EQ(1, moveVariant.index());
- EXPECT_EQ("Hello", AZStd::get<1>(moveVariant));
- // Moved from Variant should have default value
- ASSERT_EQ(1, moveVariant.index());
- EXPECT_TRUE(AZStd::get<1>(testVariant3).empty());
- }
- TEST_F(VariantTest, InPlaceTypeConstructorSucceeds)
- {
- AZStd::variant<bool, int32_t, AZStd::tuple<int32_t, bool>> inplaceIndexVariant(AZStd::in_place_type_t<int32_t>{}, 108);
- EXPECT_EQ(1, inplaceIndexVariant.index());
- auto& int32Alt = AZStd::get<1>(inplaceIndexVariant);
- EXPECT_EQ(108, int32Alt);
- }
- TEST_F(VariantTest, InPlaceTypeConstructorWithInitializerListSucceeds)
- {
- AZStd::variant<int32_t, double, AZStd::vector<int32_t>, bool> inplaceIndexVariant(AZStd::in_place_type_t<AZStd::vector<int32_t>>{}, { 1, 2, 3 }, AZStd::allocator("Variant in_place_type allocator "));
- EXPECT_EQ(2, inplaceIndexVariant.index());
- auto& vectorAlt = AZStd::get<2>(inplaceIndexVariant);
- ASSERT_EQ(3, vectorAlt.size());
- EXPECT_EQ(1, vectorAlt[0]);
- EXPECT_EQ(2, vectorAlt[1]);
- EXPECT_EQ(3, vectorAlt[2]);
- }
- TEST_F(VariantTest, InPlaceIndexConstructorSucceeds)
- {
- AZStd::variant<bool, int32_t, AZStd::tuple<int32_t, bool>> inplaceIndexVariant(AZStd::in_place_index_t<2>{}, 55, true);
- EXPECT_EQ(2, inplaceIndexVariant.index());
- auto& tupleAlt= AZStd::get<2>(inplaceIndexVariant);
- EXPECT_EQ(55, AZStd::get<0>(tupleAlt));
- EXPECT_EQ(true, AZStd::get<1>(tupleAlt));
- }
- TEST_F(VariantTest, InPlaceIndexConstructorWithInitializerListSucceeds)
- {
- AZStd::variant<float, AZStd::vector<int32_t>> inplaceIndexVariant(AZStd::in_place_index_t<1>{}, { 1, 2, 3 }, AZStd::allocator("Variant in_place_index allocator "));
- EXPECT_EQ(1, inplaceIndexVariant.index());
- auto& vectorAlt = AZStd::get<1>(inplaceIndexVariant);
- ASSERT_EQ(3, vectorAlt.size());
- EXPECT_EQ(1, vectorAlt[0]);
- EXPECT_EQ(2, vectorAlt[1]);
- EXPECT_EQ(3, vectorAlt[2]);
- }
- }
- namespace Emplace
- {
- // emplace<Type>
- TEST_F(VariantTest, TypeEmplaceUpdateCurrentAlternativeSucceeds)
- {
- AZStd::variant<bool, int32_t, AZStd::tuple<int32_t, bool>> emplaceIndexVariant(AZStd::in_place_type_t<int32_t>{}, 110);
- EXPECT_EQ(1, emplaceIndexVariant.index());
- EXPECT_EQ(110, AZStd::get<1>(emplaceIndexVariant));
- // Update current alternative
- int32_t& updatedInt = emplaceIndexVariant.emplace<int32_t>(252);
- EXPECT_EQ(1, emplaceIndexVariant.index());
- EXPECT_EQ(252, updatedInt);
- }
- TEST_F(VariantTest, TypeEmplaceUpdateDifferentAlternativeSucceeds)
- {
- AZStd::variant<bool, int32_t, AZStd::tuple<int32_t, bool>> emplaceIndexVariant(AZStd::in_place_type_t<int32_t>{}, 110);
- EXPECT_EQ(1, emplaceIndexVariant.index());
- EXPECT_EQ(110, AZStd::get<1>(emplaceIndexVariant));
- // Update different alternative
- auto& updatedTuple = emplaceIndexVariant.emplace<AZStd::tuple<int32_t, bool>>(410, true);
- EXPECT_EQ(2, emplaceIndexVariant.index());
- EXPECT_EQ(410, AZStd::get<0>(updatedTuple));
- EXPECT_TRUE(AZStd::get<1>(updatedTuple));
- }
- TEST_F(VariantTest, TypeEmplaceWithInitializerListUpdateCurrentAlternativeSucceeds)
- {
- AZStd::variant<int32_t, double, AZStd::vector<int32_t>, bool> emplaceIndexVariant(AZStd::in_place_type_t<AZStd::vector<int32_t>>{});
- EXPECT_EQ(2, emplaceIndexVariant.index());
- EXPECT_TRUE(AZStd::get<2>(emplaceIndexVariant).empty());
- // Update current alternative
- auto& updatedVector= emplaceIndexVariant.emplace<AZStd::vector<int32_t>>({ 2, 4, 6 }, AZStd::allocator("Variant emplace allocator"));
- EXPECT_EQ(2, emplaceIndexVariant.index());
- EXPECT_EQ(3, updatedVector.size());
- EXPECT_EQ(2, updatedVector[0]);
- EXPECT_EQ(4, updatedVector[1]);
- EXPECT_EQ(6, updatedVector[2]);
- }
- TEST_F(VariantTest, TypeEmplaceWithInitializerListUpdateDifferentAlternativeSucceeds)
- {
- AZStd::variant<int32_t, double, AZStd::vector<int32_t>, bool> emplaceIndexVariant(AZStd::in_place_type_t<int32_t>{}, 110);
- EXPECT_EQ(0, emplaceIndexVariant.index());
- EXPECT_EQ(110, AZStd::get<0>(emplaceIndexVariant));
- // Update different alternative
- auto& updatedVector = emplaceIndexVariant.emplace<AZStd::vector<int32_t>>({ 1, 2, 3 }, AZStd::allocator("Variant emplace allocator"));
- EXPECT_EQ(2, emplaceIndexVariant.index());
- ASSERT_EQ(3, updatedVector.size());
- EXPECT_EQ(1, updatedVector[0]);
- EXPECT_EQ(2, updatedVector[1]);
- EXPECT_EQ(3, updatedVector[2]);
- }
- // emplace<Index>
- TEST_F(VariantTest, IndexEmplaceUpdateCurrentAlternativeSucceeds)
- {
- AZStd::variant<bool, int32_t, AZStd::tuple<int32_t, bool>> emplaceIndexVariant(AZStd::in_place_type_t<int32_t>{}, 110);
- EXPECT_EQ(1, emplaceIndexVariant.index());
- EXPECT_EQ(110, AZStd::get<1>(emplaceIndexVariant));
- // Update current alternative
- int32_t& updatedInt = emplaceIndexVariant.emplace<1>(252);
- EXPECT_EQ(1, emplaceIndexVariant.index());
- EXPECT_EQ(252, updatedInt);
- }
- TEST_F(VariantTest, IndexEmplaceUpdateDifferentAlternativeSucceeds)
- {
- AZStd::variant<bool, int32_t, AZStd::tuple<int32_t, bool>> emplaceIndexVariant(AZStd::in_place_type_t<int32_t>{}, 110);
- EXPECT_EQ(1, emplaceIndexVariant.index());
- EXPECT_EQ(110, AZStd::get<1>(emplaceIndexVariant));
- // Update different alternative
- auto& updatedTuple = emplaceIndexVariant.emplace<2>(410, true);
- EXPECT_EQ(2, emplaceIndexVariant.index());
- EXPECT_EQ(410, AZStd::get<0>(updatedTuple));
- EXPECT_TRUE(AZStd::get<1>(updatedTuple));
- }
- TEST_F(VariantTest, IndexEmplaceWithInitializerListUpdateCurrentAlternativeSucceeds)
- {
- AZStd::variant<int32_t, double, AZStd::vector<int32_t>, bool> emplaceIndexVariant(AZStd::in_place_type_t<AZStd::vector<int32_t>>{}, { 336 });
- EXPECT_EQ(2, emplaceIndexVariant.index());
- EXPECT_EQ(1, AZStd::get<2>(emplaceIndexVariant).size());
- EXPECT_EQ(336, AZStd::get<2>(emplaceIndexVariant).at(0));
- // Update current alternative
- auto& updatedVector = emplaceIndexVariant.emplace<2>({ 17, -54 });
- EXPECT_EQ(2, emplaceIndexVariant.index());
-
- EXPECT_EQ(2, updatedVector.size());
- EXPECT_EQ(17, updatedVector[0]);
- EXPECT_EQ(-54, updatedVector[1]);
- }
- TEST_F(VariantTest, IndexEmplaceWithInitializerListUpdateDifferentAlternativeSucceeds)
- {
- AZStd::variant<int32_t, double, AZStd::vector<int32_t>, bool> emplaceIndexVariant(AZStd::in_place_type_t<int32_t>{}, 110);
- EXPECT_EQ(0, emplaceIndexVariant.index());
- EXPECT_EQ(110, AZStd::get<0>(emplaceIndexVariant));
- // Update different alternative
- auto& updatedVector = emplaceIndexVariant.emplace<2>({ 1, 2, 3 }, AZStd::allocator("Variant emplace allocator"));
- EXPECT_EQ(2, emplaceIndexVariant.index());
- ASSERT_EQ(3, updatedVector.size());
- EXPECT_EQ(1, updatedVector[0]);
- EXPECT_EQ(2, updatedVector[1]);
- EXPECT_EQ(3, updatedVector[2]);
- }
- }
- namespace GetAlternative
- {
- //get_if<Index>
- TEST_F(VariantTest, HoldsAlternativeSucceeds)
- {
- AZStd::variant<double, int32_t> testVariant(AZStd::in_place_type_t<int32_t>{}, 17);
- EXPECT_FALSE(AZStd::holds_alternative<double>(testVariant));
- EXPECT_TRUE(AZStd::holds_alternative<int32_t>(testVariant));
- testVariant = 8.0;
- EXPECT_TRUE(AZStd::holds_alternative<double>(testVariant));
- EXPECT_FALSE(AZStd::holds_alternative<int32_t>(testVariant));
- }
- TEST_F(VariantTest, IndexGetIfWithConstVariantSingleAlternativeSucceeds)
- {
- const AZStd::variant<int32_t> testVariant(17);
- const int32_t* testAlt = AZStd::get_if<0>(&testVariant);
- ASSERT_NE(nullptr, testAlt);
- EXPECT_EQ(17, *testAlt);
- }
- TEST_F(VariantTest, IndexGetIfWithConstVariantMultipleAlternativeSucceeds)
- {
- const AZStd::variant<int32_t, double> testVariant(32.0);
- const double* testAlt = AZStd::get_if<1>(&testVariant);
- ASSERT_NE(nullptr, testAlt);
- EXPECT_DOUBLE_EQ(32.0, *testAlt);
- }
- TEST_F(VariantTest, IndexGetIfWithConstVariantMultipleAlternativeFails)
- {
- const AZStd::variant<int32_t, double> testVariant(32.0);
- const int32_t* testAlt = AZStd::get_if<0>(&testVariant);
- EXPECT_EQ(nullptr, testAlt);
- }
- TEST_F(VariantTest, IndexGetIfWithVariantSingleAlternativeSucceeds)
- {
- AZStd::variant<int32_t> testVariant(17);
- int32_t* testAlt = AZStd::get_if<0>(&testVariant);
- ASSERT_NE(nullptr, testAlt);
- EXPECT_EQ(17, *testAlt);
- }
- TEST_F(VariantTest, IndexGetIfWithVariantMultipleAlternativeSucceeds)
- {
- AZStd::variant<int32_t, double> testVariant(32.0);
- double* testAlt = AZStd::get_if<1>(&testVariant);
- ASSERT_NE(nullptr, testAlt);
- EXPECT_DOUBLE_EQ(32.0, *testAlt);
- }
- // get_if<Type>
- TEST_F(VariantTest, IndexGetIfWithVariantMultipleAlternativeFails)
- {
- AZStd::variant<int32_t, double> testVariant(32.0);
- int32_t* testAlt = AZStd::get_if<0>(&testVariant);
- EXPECT_EQ(nullptr, testAlt);
- }
- TEST_F(VariantTest, TypeGetIfWithConstVariantSingleAlternativeSucceeds)
- {
- const AZStd::variant<int32_t> testVariant(17);
- const int32_t* testAlt = AZStd::get_if<int32_t>(&testVariant);
- ASSERT_NE(nullptr, testAlt);
- EXPECT_EQ(17, *testAlt);
- }
- TEST_F(VariantTest, TypeGetIfWithConstVariantMultipleAlternativeSucceeds)
- {
- const AZStd::variant<int32_t, double> testVariant(32.0);
- const auto testAlt = AZStd::get_if<double>(&testVariant);
- ASSERT_NE(nullptr, testAlt);
- EXPECT_DOUBLE_EQ(32.0, *testAlt);
- }
- TEST_F(VariantTest, TypeGetIfWithConstVariantMultipleAlternativeFails)
- {
- const AZStd::variant<int32_t, double> testVariant(32.0);
- const auto testAlt = AZStd::get_if<int32_t>(&testVariant);
- EXPECT_EQ(nullptr, testAlt);
- }
- TEST_F(VariantTest, TypeGetIfWithVariantSingleAlternativeSucceeds)
- {
- AZStd::variant<int32_t> testVariant(17);
- auto testAlt = AZStd::get_if<int32_t>(&testVariant);
- ASSERT_NE(nullptr, testAlt);
- EXPECT_EQ(17, *testAlt);
- }
- TEST_F(VariantTest, TypeGetIfWithVariantMultipleAlternativeSucceeds)
- {
- AZStd::variant<int32_t, double> testVariant(32.0);
- auto testAlt = AZStd::get_if<double>(&testVariant);
- ASSERT_NE(nullptr, testAlt);
- EXPECT_DOUBLE_EQ(32.0, *testAlt);
- }
- TEST_F(VariantTest, TypeGetIfWithVariantMultipleAlternativeFails)
- {
- AZStd::variant<int32_t, double> testVariant(32.0);
- auto testAlt = AZStd::get_if<int32_t>(&testVariant);
- EXPECT_EQ(nullptr, testAlt);
- }
- // get<Index>
- TEST_F(VariantTest, IndexGetLValueVariantNonConstAlternativeSucceeds)
- {
- AZStd::variant<int32_t, const int64_t> testVariant(6);
- ASSERT_EQ(0, testVariant.index());
- EXPECT_EQ(6, AZStd::get<0>(testVariant));
- static_assert(AZStd::is_same<decltype(AZStd::get<0>(testVariant)), int32_t&>::value,
- "AZStd::get should return lvalue reference to non-const alternative for non-const variant");
- }
- TEST_F(VariantTest, IndexGetLValueVariantConstAlternativeSucceeds)
- {
- // Set const alternative on construct
- AZStd::variant<int32_t, const int64_t> testVariant(static_cast<int64_t>(23LL));
- ASSERT_EQ(1, testVariant.index());
- EXPECT_EQ(23LL, AZStd::get<1>(testVariant));
- static_assert(AZStd::is_same<decltype(AZStd::get<1>(testVariant)), const int64_t&>::value,
- "AZStd::get should return const lvalue reference to const alternativefor non-const variant");
- }
- TEST_F(VariantTest, IndexGetConstLValueVariantNonConstAlternativeSucceeds)
- {
- const AZStd::variant<int32_t, const int64_t> testVariant(6);
- ASSERT_EQ(0, testVariant.index());
- EXPECT_EQ(6, AZStd::get<0>(testVariant));
- static_assert(AZStd::is_same<decltype(AZStd::get<0>(testVariant)), const int32_t&>::value,
- "AZStd::get should return const lvalue reference to non-const alternative for const variant");
- }
- TEST_F(VariantTest, IndexGetConstLValueVariantConstAlternativeSucceeds)
- {
- // Set const alternative on construct
- const AZStd::variant<int32_t, const int64_t> testVariant(static_cast<int64_t>(23LL));
- ASSERT_EQ(1, testVariant.index());
- EXPECT_EQ(23LL, AZStd::get<1>(testVariant));
- static_assert(AZStd::is_same<decltype(AZStd::get<1>(testVariant)), const int64_t&>::value,
- "AZStd::get should return const lvalue reference to const alternative for const variant");
- }
- TEST_F(VariantTest, IndexGetRValueVariantNonConstAlternativeSucceeds)
- {
- AZStd::variant<int32_t, const int64_t> testVariant(6);
- ASSERT_EQ(0, testVariant.index());
- static_assert(AZStd::is_same<decltype(AZStd::get<0>(AZStd::move(testVariant))), int32_t&&>::value,
- "AZStd::get should return rvalue reference to non-const alternative for non-const variant");
- EXPECT_EQ(6, AZStd::get<0>(AZStd::move(testVariant)));
- }
- TEST_F(VariantTest, IndexGetRValueVariantConstAlternativeSucceeds)
- {
- // Set const alternative on construct
- AZStd::variant<int32_t, const int64_t> testVariant(static_cast<int64_t>(23LL));
- ASSERT_EQ(1, testVariant.index());
-
- static_assert(AZStd::is_same<decltype(AZStd::get<1>(AZStd::move(testVariant))), const int64_t&&>::value,
- "AZStd::get should return const rvalue reference to const alternative for non-const variant");
- EXPECT_EQ(23LL, AZStd::get<1>(AZStd::move(testVariant)));
- }
- TEST_F(VariantTest, IndexGetConstRValueVariantNonConstAlternativeSucceeds)
- {
- const AZStd::variant<int32_t, const int64_t> testVariant(6);
- ASSERT_EQ(0, testVariant.index());
-
- static_assert(AZStd::is_same<decltype(AZStd::get<0>(AZStd::move(testVariant))), const int32_t&&>::value,
- "AZStd::get should return const rvalue reference to non-const alternative for const variant");
- EXPECT_EQ(6, AZStd::get<0>(AZStd::move(testVariant)));
- }
- TEST_F(VariantTest, IndexGetConstRValueVariantConstAlternativeSucceeds)
- {
- // Set const alternative on construct
- const AZStd::variant<int32_t, const int64_t> testVariant(static_cast<int64_t>(23LL));
- ASSERT_EQ(1, testVariant.index());
-
- static_assert(AZStd::is_same<decltype(AZStd::get<1>(AZStd::move(testVariant))), const int64_t&&>::value,
- "AZStd::get should return const rvalue reference to const alternative for const variant");
- EXPECT_EQ(23LL, AZStd::get<1>(AZStd::move(testVariant)));
- }
- // get<Type>
- TEST_F(VariantTest, TypeGetLValueVariantNonConstAlternativeSucceeds)
- {
- AZStd::variant<int32_t, const int64_t> testVariant(6);
- ASSERT_EQ(0, testVariant.index());
- EXPECT_EQ(6, AZStd::get<int32_t>(testVariant));
- static_assert(AZStd::is_same<decltype(AZStd::get<int32_t>(testVariant)), int32_t&>::value,
- "AZStd::get should return lvalue reference to non-const alternative for non-const variant");
- }
- TEST_F(VariantTest, TypeGetLValueVariantConstAlternativeSucceeds)
- {
- // Set const alternative on construct
- AZStd::variant<int32_t, const int64_t> testVariant(static_cast<int64_t>(23LL));
- ASSERT_EQ(1, testVariant.index());
- EXPECT_EQ(23LL, AZStd::get<const int64_t>(testVariant));
- static_assert(AZStd::is_same<decltype(AZStd::get<const int64_t>(testVariant)), const int64_t&>::value,
- "AZStd::get should return const lvalue reference to const alternativefor non-const variant");
- }
- TEST_F(VariantTest, TypeGetConstLValueVariantNonConstAlternativeSucceeds)
- {
- const AZStd::variant<int32_t, const int64_t> testVariant(6);
- ASSERT_EQ(0, testVariant.index());
- EXPECT_EQ(6, AZStd::get<int32_t>(testVariant));
- static_assert(AZStd::is_same<decltype(AZStd::get<int32_t>(testVariant)), const int32_t&>::value,
- "AZStd::get should return const lvalue reference to non-const alternative for const variant");
- }
- TEST_F(VariantTest, TypeGetConstLValueVariantConstAlternativeSucceeds)
- {
- // Set const alternative on construct
- const AZStd::variant<int32_t, const int64_t> testVariant(static_cast<int64_t>(23LL));
- ASSERT_EQ(1, testVariant.index());
- EXPECT_EQ(23LL, AZStd::get<const int64_t>(testVariant));
- static_assert(AZStd::is_same<decltype(AZStd::get<const int64_t>(testVariant)), const int64_t&>::value,
- "AZStd::get should return const lvalue reference to const alternative for const variant");
- }
- TEST_F(VariantTest, TypeGetRValueVariantNonConstAlternativeSucceeds)
- {
- AZStd::variant<int32_t, const int64_t> testVariant(6);
- ASSERT_EQ(0, testVariant.index());
- static_assert(AZStd::is_same<decltype(AZStd::get<int32_t>(AZStd::move(testVariant))), int32_t&&>::value,
- "AZStd::get should return rvalue reference to non-const alternative for non-const variant");
- EXPECT_EQ(6, AZStd::get<int32_t>(AZStd::move(testVariant)));
- }
- TEST_F(VariantTest, TypeGetRValueVariantConstAlternativeSucceeds)
- {
- // Set const alternative on construct
- AZStd::variant<int32_t, const int64_t> testVariant(static_cast<int64_t>(23LL));
- ASSERT_EQ(1, testVariant.index());
- static_assert(AZStd::is_same<decltype(AZStd::get<const int64_t>(AZStd::move(testVariant))), const int64_t&&>::value,
- "AZStd::get should return const rvalue reference to const alternative for non-const variant");
- EXPECT_EQ(23LL, AZStd::get<const int64_t>(AZStd::move(testVariant)));
- }
- TEST_F(VariantTest, TypeGetConstRValueVariantNonConstAlternativeSucceeds)
- {
- const AZStd::variant<int32_t, const int64_t> testVariant(6);
- ASSERT_EQ(0, testVariant.index());
- static_assert(AZStd::is_same<decltype(AZStd::get<int32_t>(AZStd::move(testVariant))), const int32_t&&>::value,
- "AZStd::get should return const rvalue reference to non-const alternative for const variant");
- EXPECT_EQ(6, AZStd::get<int32_t>(AZStd::move(testVariant)));
- }
- TEST_F(VariantTest, TypeGetConstRValueVariantConstAlternativeSucceeds)
- {
- // Set const alternative on construct
- const AZStd::variant<int32_t, const int64_t> testVariant(static_cast<int64_t>(23LL));
- ASSERT_EQ(1, testVariant.index());
- static_assert(AZStd::is_same<decltype(AZStd::get<const int64_t>(AZStd::move(testVariant))), const int64_t&&>::value,
- "AZStd::get should return const rvalue reference to const alternative for const variant");
- EXPECT_EQ(23LL, AZStd::get<const int64_t>(AZStd::move(testVariant)));
- }
- }
- namespace VisitorQualifier
- {
- // non-const lvalue visitor
- TEST_F(VariantTest, VisitForwardsLValueMemberVisitorCorrectly_WithSingleAlternativeVariant)
- {
- VariantTestInternal::MemberFuncQualifierCallable callable{};
- AZStd::variant<int16_t> testVariant(static_cast<int16_t>(7));
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, testVariant);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::lvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsLValueMemberVisitorCorrectly_WithMultipleAlternativeVariant)
- {
- VariantTestInternal::MemberFuncQualifierCallable callable{};
- AZStd::variant<int16_t, AZStd::string> testVariant2("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, testVariant2);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::lvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsLValueMemberVisitorCorrectly_WithMultipleVariants)
- {
- VariantTestInternal::MemberFuncQualifierCallable callable{};
- AZStd::variant<float, double> testVariant3(2.0);
- AZStd::variant<AZStd::string_view, const char*> testVariant4("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, testVariant3, testVariant4);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::lvalue_ref, calledFunc);
- }
- // const lvalue visitor
- TEST_F(VariantTest, VisitForwardsConstLValueMemberVisitorCorrectly_WithSingleAlternativeVariant)
- {
- const VariantTestInternal::MemberFuncQualifierCallable callable{};
- AZStd::variant<int16_t> testVariant(static_cast<int16_t>(7));
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, testVariant);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::const_lvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsConstLValueMemberVisitorCorrectly_WithMultipleAlternativeVariant)
- {
- const VariantTestInternal::MemberFuncQualifierCallable callable{};
- AZStd::variant<int16_t, AZStd::string> testVariant2("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, testVariant2);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::const_lvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsConstLValueMemberVisitorCorrectly_WithMultipleVariants)
- {
- const VariantTestInternal::MemberFuncQualifierCallable callable{};
- AZStd::variant<float, double> testVariant3(2.0);
- AZStd::variant<AZStd::string_view, const char*> testVariant4("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, testVariant3, testVariant4);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::const_lvalue_ref, calledFunc);
- }
- // non-const rvalue visitor
- TEST_F(VariantTest, VisitForwardsRValueMemberVisitorCorrectly_WithSingleAlternativeVariant)
- {
- VariantTestInternal::MemberFuncQualifierCallable callable{};
- AZStd::variant<int16_t> testVariant(static_cast<int16_t>(7));
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(AZStd::move(callable), testVariant);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::rvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsRValueMemberVisitorCorrectly_WithMultipleAlternativeVariant)
- {
- VariantTestInternal::MemberFuncQualifierCallable callable{};
- AZStd::variant<int16_t, AZStd::string> testVariant2("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(AZStd::move(callable), testVariant2);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::rvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsRValueMemberVisitorCorrectly_WithMultipleVariants)
- {
- VariantTestInternal::MemberFuncQualifierCallable callable{};
- AZStd::variant<float, double> testVariant3(2.0);
- AZStd::variant<AZStd::string_view, const char*> testVariant4("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(AZStd::move(callable), testVariant3, testVariant4);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::rvalue_ref, calledFunc);
- }
- // const rvalue visitor
- TEST_F(VariantTest, VisitForwardsConstRValueMemberVisitorCorrectly_WithSingleAlternativeVariant)
- {
- const VariantTestInternal::MemberFuncQualifierCallable callable{};
- AZStd::variant<int16_t> testVariant(static_cast<int16_t>(7));
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(AZStd::move(callable), testVariant);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::const_rvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsConstRValueMemberVisitorCorrectly_WithMultiAlternativeVariant)
- {
- const VariantTestInternal::MemberFuncQualifierCallable callable{};
- AZStd::variant<int16_t, AZStd::string> testVariant2("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(AZStd::move(callable), testVariant2);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::const_rvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsConstRValueMemberVisitorCorrectly_WithMultipleVariants)
- {
- const VariantTestInternal::MemberFuncQualifierCallable callable{};
- AZStd::variant<float, double> testVariant3(2.0);
- AZStd::variant<AZStd::string_view, const char*> testVariant4("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(AZStd::move(callable), testVariant3, testVariant4);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::const_rvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitWithExplicitReturnTypeSucceeds)
- {
- auto returnConstCharPtrVisitor = [](auto&& variantAlt) -> const char*
- {
- (void)variantAlt;
- return AZStd::is_same<AZStd::remove_cvref_t<decltype(variantAlt)>, const char*>::value ? "Boat" : "Willy";
- };
- AZStd::variant<float, const char*> testVariant1(static_cast<const char*>("Steam"));
- auto testResultData = AZStd::visit<AZStd::string_view>(returnConstCharPtrVisitor, testVariant1);
- EXPECT_FALSE(testResultData.empty());
- EXPECT_EQ("Boat", testResultData);
- }
- }
- namespace VariantQualifier
- {
- // non-const lvalue variant
- TEST_F(VariantTest, VisitForwardsLValueVariantCorrectly_WithSingleAlternativeVariant)
- {
- VariantTestInternal::ParameterQualifierCallable callable{};
- AZStd::variant<int16_t> testVariant(static_cast<int16_t>(7));
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, testVariant);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::lvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsLValueVariantCorrectly_WithMultipleAlternativeVariant)
- {
- VariantTestInternal::ParameterQualifierCallable callable{};
- AZStd::variant<int16_t, AZStd::string> testVariant2("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, testVariant2);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::lvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsLValueVariantCorrectly_WithMultipleVariants)
- {
- VariantTestInternal::ParameterQualifierCallable callable{};
- AZStd::variant<float, double> testVariant3(2.0);
- AZStd::variant<AZStd::string_view, const char*> testVariant4("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, testVariant3, testVariant4);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::lvalue_ref, calledFunc);
- }
- // const lvalue variant
- TEST_F(VariantTest, VisitForwardsConstLValueVariantCorrectly_WithSingleAlternativeVariant)
- {
- VariantTestInternal::ParameterQualifierCallable callable{};
- const AZStd::variant<int16_t> testVariant(static_cast<int16_t>(7));
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, testVariant);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::const_lvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsConstLValueVariantCorrectly_WithMultipleAlternativeVariant)
- {
- VariantTestInternal::ParameterQualifierCallable callable{};
- const AZStd::variant<int16_t, AZStd::string> testVariant2("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, testVariant2);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::const_lvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsConstLValueVariantCorrectly_WithMultipleVariants)
- {
- VariantTestInternal::ParameterQualifierCallable callable{};
- const AZStd::variant<float, double> testVariant3(2.0);
- const AZStd::variant<AZStd::string_view, const char*> testVariant4("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, testVariant3, testVariant4);
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::const_lvalue_ref, calledFunc);
- }
- // non-const rvalue variant
- TEST_F(VariantTest, VisitForwardsRValueVariantCorrectly_WithSingleAlternativeVariant)
- {
- VariantTestInternal::ParameterQualifierCallable callable{};
- AZStd::variant<int16_t> testVariant(static_cast<int16_t>(7));
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, AZStd::move(testVariant));
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::rvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsRValueVariantCorrectly_WithMultipleAlternativeVariant)
- {
- VariantTestInternal::ParameterQualifierCallable callable{};
- AZStd::variant<int16_t, AZStd::string> testVariant2("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, AZStd::move(testVariant2));
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::rvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsRValueVariantCorrectly_WithMultipleVariants)
- {
- VariantTestInternal::ParameterQualifierCallable callable{};
- AZStd::variant<float, double> testVariant3(2.0);
- const AZStd::variant<AZStd::string_view, const char*> testVariant4("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, AZStd::move(testVariant3), AZStd::move(testVariant4));
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::rvalue_ref, calledFunc);
- }
- // const rvalue variant
- TEST_F(VariantTest, VisitForwardsConstRValueVariantCorrectly_WithSingleAlternativeVariant)
- {
- VariantTestInternal::ParameterQualifierCallable callable{};
- const AZStd::variant<int16_t> testVariant(static_cast<int16_t>(7));
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, AZStd::move(testVariant));
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::const_rvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsConstRValueVariantCorrectly_WithMultipleAlternativeVariant)
- {
- VariantTestInternal::ParameterQualifierCallable callable{};
- const AZStd::variant<int16_t, AZStd::string> testVariant2("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, AZStd::move(testVariant2));
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::const_rvalue_ref, calledFunc);
- }
- TEST_F(VariantTest, VisitForwardsConstRValueVariantCorrectly_WithMultipleVariants)
- {
- VariantTestInternal::ParameterQualifierCallable callable{};
- const AZStd::variant<float, double> testVariant3(2.0);
- const AZStd::variant<AZStd::string_view, const char*> testVariant4("ConstMember");
- VariantTestInternal::MemberFuncQualifiers calledFunc = AZStd::visit(callable, AZStd::move(testVariant3), AZStd::move(testVariant4));
- EXPECT_EQ(VariantTestInternal::MemberFuncQualifiers::const_rvalue_ref, calledFunc);
- }
- }
- TEST_F(VariantTest, VisitIsEvaluatedInConstexprContextSucceeds)
- {
- constexpr VariantTestInternal::ConstexprVisitorHelper constexprHelper{};
- using TestVariant = AZStd::variant<uint32_t>;
- // variant visiting ends up calling array operator [] which is constexpr but calls AZ_Assert which is not constexpr, so it cannot be solved in a static_assert
- constexpr TestVariant testVariant(21);
- static_assert(AZStd::visit(constexprHelper, testVariant) == 21, "Constexpr Variant not equal to expected result");
- EXPECT_EQ(21, AZStd::visit(constexprHelper, testVariant));
- }
- TEST_F(VariantTest, VisitWithMultipleAlternativeEvaluatedInConstexprContextSucceeds)
- {
- constexpr VariantTestInternal::ConstexprVisitorHelper constexprHelper{};
- using TestVariant = AZStd::variant<int16_t, int64_t, char>;
- // variant visiting ends up calling array operator [] which is constexpr but calls AZ_Assert which is not constexpr, so it cannot be solved in a static_assert
- constexpr TestVariant testVariant(static_cast<int64_t>(42LL));
- static_assert(AZStd::visit(constexprHelper, testVariant) == 42, "Constexpr Variant not equal to expected result");
- EXPECT_EQ(42, AZStd::visit(constexprHelper, testVariant));
- }
- TEST_F(VariantTest, VisitWithMultipleVariantEvaluatedInConstexprContextSucceeds)
- {
- using TestVariant1 = AZStd::variant<int32_t>;
- using TestVariant2 = AZStd::variant<int32_t, char*, int64_t>;
- using TestVariant3 = AZStd::variant<bool, uint32_t, int32_t>;
- // variant visiting ends up calling array operator [] which is constexpr but calls AZ_Assert which is not constexpr, so it cannot be solved in a static_assert
- constexpr TestVariant1 testVariant1;
- constexpr TestVariant2 testVariant2(nullptr);
- constexpr TestVariant3 testVariant3;
- static_assert(AZStd::visit(VariantTestInternal::VariadicVariantSizeof{}, testVariant1, testVariant2, testVariant3) == 3,
- "Sizeof visitor should return the same number of variants supplied to it");
- EXPECT_EQ(3, AZStd::visit(VariantTestInternal::VariadicVariantSizeof{}, testVariant1, testVariant2, testVariant3));
- }
- TEST_F(VariantTest, VisitorAcceptsNonConstLValueReferenceSucceeds)
- {
- AZStd::variant<VariantTestInternal::TrivialAlt> variantAlt;
- auto nonConstLRefVisitor = [](VariantTestInternal::TrivialAlt&)
- {
- };
- AZStd::visit(nonConstLRefVisitor, variantAlt);
- }
- TEST_F(VariantTest, VisitorAcceptsNonConstRValueReferenceSucceeds)
- {
- AZStd::variant<VariantTestInternal::TrivialAlt> variantAlt;
- auto nonConstRRefVisitor = [](VariantTestInternal::TrivialAlt&&)
- {
- };
- AZStd::visit(nonConstRRefVisitor, AZStd::move(variantAlt));
- }
- namespace HashFunctions
- {
- TEST_F(VariantTest, HashMonostateSucceeds)
- {
- AZStd::monostate testMonostate1;
- size_t resultHash1 = AZStd::hash<AZStd::monostate>{}(testMonostate1);
- const AZStd::monostate testMonostate2 {};
- size_t resultHash2 = AZStd::hash<AZStd::monostate>{}(testMonostate2);
- EXPECT_EQ(resultHash1, resultHash2);
- }
- TEST_F(VariantTest, HashVariantAlternativeOfSameTypeHashesToDifferentResults)
- {
- using TestVariant = AZStd::variant<AZStd::monostate, AZStd::monostate>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{});
- TestVariant testVariant2(AZStd::in_place_index_t<1>{});
- size_t resultHash1 = AZStd::hash<TestVariant>{}(testVariant1);
- size_t resultHash2 = AZStd::hash<TestVariant>{}(testVariant2);
- EXPECT_NE(resultHash1, resultHash2);
- }
- TEST_F(VariantTest, HashVariantDifferentValuesForSameAlternativeHashesToDifferentResults)
- {
- using TestVariant = AZStd::variant<int64_t, int32_t, int64_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{}, 42);
- TestVariant testVariant2(AZStd::in_place_index_t<1>{}, 43);
- size_t resultHash1 = AZStd::hash<TestVariant>{}(testVariant1);
- size_t resultHash2 = AZStd::hash<TestVariant>{}(testVariant2);
- EXPECT_NE(resultHash1, resultHash2);
- }
- TEST_F(VariantTest, HashVariantCopyOfVariantHashesToSameResult)
- {
- using TestVariant = AZStd::variant<int64_t, int32_t, int64_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{}, 47);
- TestVariant copyVariant(testVariant1);
- size_t resultHash1 = AZStd::hash<TestVariant>{}(testVariant1);
- size_t resultHash2 = AZStd::hash<TestVariant>{}(copyVariant);
- EXPECT_EQ(resultHash1, resultHash2);
- }
- TEST_F(VariantTest, HashVariantDefaultConstructedVariantHashesToSameValue)
- {
- using TestVariant = AZStd::variant<int64_t, int32_t, int64_t>;
- TestVariant testVariant1;
- TestVariant testVariant2;
- size_t resultHash1 = AZStd::hash<TestVariant>{}(testVariant1);
- size_t resultHash2 = AZStd::hash<TestVariant>{}(testVariant2);
- EXPECT_EQ(resultHash1, resultHash2);
- }
- TEST_F(VariantTest, HashVariantHashRemainsStableForSameValue)
- {
- using TestVariant = AZStd::variant<int64_t, int32_t, int64_t>;
- constexpr int64_t initialValue = 84;
- TestVariant testVariant1(AZStd::in_place_index_t<2>{}, initialValue);
- size_t expectedHash = AZStd::hash<TestVariant>{}(testVariant1);
- AZStd::get<2>(testVariant1) = 74;
- size_t resultHash = AZStd::hash<TestVariant>{}(testVariant1);
- EXPECT_NE(expectedHash, resultHash);
- AZStd::get<2>(testVariant1) = initialValue;
- resultHash = AZStd::hash<TestVariant>{}(testVariant1);
- EXPECT_EQ(expectedHash, resultHash);
- }
- }
- namespace RelationalOperators
- {
- // equal
- TEST_F(VariantTest, OperatorEqualForVariantWithSameAlternativeAndValueSucceeds)
- {
- using TestVariant = AZStd::variant<int64_t, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{}, 7);
- TestVariant testVariant2(AZStd::in_place_index_t<0>{}, 7);
- EXPECT_TRUE(testVariant1 == testVariant2);
- }
- TEST_F(VariantTest, OperatorEqualForVariantWithSameAlternativeAndDifferentValueFails)
- {
- using TestVariant = AZStd::variant<int64_t, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{}, 7);
- TestVariant testVariant2(AZStd::in_place_index_t<0>{}, 8);
- EXPECT_FALSE(testVariant1 == testVariant2);
- }
- TEST_F(VariantTest, OperatorEqualForVariantWithDifferentAlternativeFails)
- {
- using TestVariant = AZStd::variant<int64_t, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{}, 7);
- TestVariant testVariant2(AZStd::in_place_index_t<1>{}, 7);
- EXPECT_FALSE(testVariant1 == testVariant2);
- }
- // not-equal
- TEST_F(VariantTest, OperatorNotEqualForVariantWithSameAlternativeAndValueFails)
- {
- using TestVariant = AZStd::variant<int64_t, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{}, 7);
- TestVariant testVariant2(AZStd::in_place_index_t<0>{}, 7);
- EXPECT_FALSE(testVariant1 != testVariant2);
- }
- TEST_F(VariantTest, OperatorNotEqualForVariantWithSameAlternativeAndDifferentValueSucceeds)
- {
- using TestVariant = AZStd::variant<int64_t, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{}, 7);
- TestVariant testVariant2(AZStd::in_place_index_t<0>{}, 8);
- EXPECT_TRUE(testVariant1 != testVariant2);
- }
- TEST_F(VariantTest, OperatorNotEqualForVariantWithDifferentAlternativeSucceeds)
- {
- using TestVariant = AZStd::variant<int8_t, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{}, static_cast<int8_t>(7));
- TestVariant testVariant2(AZStd::in_place_index_t<1>{}, 7);
- EXPECT_TRUE(testVariant1 != testVariant2);
- }
- // less
- TEST_F(VariantTest, OperatorLessForVariantWithSameAlternativeAndValueFails)
- {
- using TestVariant = AZStd::variant<int64_t, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{}, 7);
- TestVariant testVariant2(AZStd::in_place_index_t<0>{}, 7);
- EXPECT_FALSE(testVariant1 < testVariant2);
- }
- TEST_F(VariantTest, OperatorLessForVariantWithSameAlternativeAndDifferentValueSucceeds)
- {
- using TestVariant = AZStd::variant<int64_t, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<1>{}, 7);
- TestVariant testVariant2(AZStd::in_place_index_t<1>{}, 8);
- EXPECT_TRUE(testVariant1 < testVariant2);
- EXPECT_FALSE(testVariant2 < testVariant1);
- }
- TEST_F(VariantTest, OperatorLessForVariantWithDifferentAlternativeSucceeds)
- {
- using TestVariant = AZStd::variant<int64_t, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{}, 10000);
- TestVariant testVariant2(AZStd::in_place_index_t<1>{}, 7);
- EXPECT_TRUE(testVariant1 < testVariant2);
- EXPECT_FALSE(testVariant2 < testVariant1);
- }
- // greater
- TEST_F(VariantTest, OperatorGreaterForVariantWithSameAlternativeAndValueFails)
- {
- using TestVariant = AZStd::variant<int64_t, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{}, 7);
- TestVariant testVariant2(AZStd::in_place_index_t<0>{}, 7);
- EXPECT_FALSE(testVariant1 > testVariant2);
- }
- TEST_F(VariantTest, OperatorGreaterForVariantWithSameAlternativeAndDifferentValueSucceeds)
- {
- using TestVariant = AZStd::variant<int8_t, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<1>{}, 427);
- TestVariant testVariant2(AZStd::in_place_index_t<1>{}, 321);
- EXPECT_TRUE(testVariant1 > testVariant2);
- EXPECT_FALSE(testVariant2 > testVariant1);
- }
- TEST_F(VariantTest, OperatorGreaterForVariantWithDifferentAlternativeSucceeds)
- {
- using TestVariant = AZStd::variant<int64_t, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<1>{}, -5000);
- TestVariant testVariant2(AZStd::in_place_index_t<0>{}, 17);
- EXPECT_TRUE(testVariant1 > testVariant2);
- EXPECT_FALSE(testVariant2 > testVariant1);
- }
- // less equal
- TEST_F(VariantTest, OperatorLessEqualForVariantWithSameAlternativeAndValueSucceeds)
- {
- using TestVariant = AZStd::variant<int64_t, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{}, 7);
- TestVariant testVariant2(AZStd::in_place_index_t<0>{}, 7);
- EXPECT_TRUE(testVariant1 <= testVariant2);
- }
- TEST_F(VariantTest, OperatorLessEqualForVariantWithSameAlternativeAndDifferentValueSucceeds)
- {
- using TestVariant = AZStd::variant<int8_t, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<1>{}, 19);
- TestVariant testVariant2(AZStd::in_place_index_t<1>{}, 21);
- TestVariant testVariant3(AZStd::in_place_index_t<1>{}, 21);
- EXPECT_TRUE(testVariant1 <= testVariant2);
- EXPECT_FALSE(testVariant2 <= testVariant1);
- EXPECT_TRUE(testVariant2 <= testVariant3);
- }
- TEST_F(VariantTest, OperatorLessEqualForVariantWithDifferentAlternativeSucceeds)
- {
- using TestVariant = AZStd::variant<bool, float>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{}, false);
- TestVariant testVariant2(AZStd::in_place_index_t<1>{}, 16.0f);
- EXPECT_TRUE(testVariant1 <= testVariant2);
- EXPECT_FALSE(testVariant2 <= testVariant1);
- }
- // greater equal
- TEST_F(VariantTest, OperatorGreaterEqualForVariantWithSameAlternativeAndValueSucceeds)
- {
- using TestVariant = AZStd::variant<AZStd::string, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{}, "Hello");
- TestVariant testVariant2(AZStd::in_place_index_t<0>{}, "Hello");
- EXPECT_TRUE(testVariant1 >= testVariant2);
- }
- TEST_F(VariantTest, OperatorGreaterEqualForVariantWithSameAlternativeAndDifferentValueSucceeds)
- {
- using TestVariant = AZStd::variant<int16_t, AZStd::string>;
- TestVariant testVariant1(AZStd::in_place_index_t<1>{}, "World");
- TestVariant testVariant2(AZStd::in_place_index_t<1>{}, "Worlc");
- TestVariant testVariant3(AZStd::in_place_index_t<1>{}, "Worlc");
- EXPECT_TRUE(testVariant1 >= testVariant2);
- EXPECT_FALSE(testVariant2 >= testVariant1);
- EXPECT_TRUE(testVariant2 >= testVariant3);
- }
- TEST_F(VariantTest, OperatorGreaterEqualForVariantWithDifferentAlternativeSucceeds)
- {
- using TestVariant = AZStd::variant<void*, float>;
- TestVariant testVariant1(AZStd::in_place_index_t<1>{}, 34.5f);
- TestVariant testVariant2(AZStd::in_place_index_t<0>{}, nullptr);
- EXPECT_TRUE(testVariant1 >= testVariant2);
- EXPECT_FALSE(testVariant2 >= testVariant1);
- }
- }
- namespace VariantSwap
- {
- TEST_F(VariantTest, SwapSameAlternativeSucceeds)
- {
- using TestVariant = AZStd::variant<AZStd::string, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<0>{}, "Hello");
- TestVariant testVariant2(AZStd::in_place_index_t<0>{}, "World");
- testVariant1.swap(testVariant2);
- EXPECT_EQ("World", AZStd::get<0>(testVariant1));
- EXPECT_EQ("Hello", AZStd::get<0>(testVariant2));
- }
- TEST_F(VariantTest, SwapDifferentAlternativeSucceeds)
- {
- using TestVariant = AZStd::variant<AZStd::string, int32_t>;
- TestVariant testVariant1(AZStd::in_place_index_t<1>{}, 501);
- TestVariant testVariant2(AZStd::in_place_index_t<0>{}, "TestCode");
- testVariant1.swap(testVariant2);
- ASSERT_EQ(0, testVariant1.index());
- EXPECT_EQ("TestCode", AZStd::get<0>(testVariant1));
- ASSERT_EQ(1, testVariant2.index());
- EXPECT_EQ(501, AZStd::get<1>(testVariant2));
- }
- TEST_F(VariantTest, SwapWithMoveOnlyTypeSucceeds)
- {
- using TestVariant = AZStd::variant<VariantTestInternal::MoveOnly>;
- TestVariant testVariant1;
- AZStd::get<0>(testVariant1).m_value = 10;
- TestVariant testVariant2;
- AZStd::get<0>(testVariant2).m_value = 20;
- testVariant1.swap(testVariant2);
- EXPECT_EQ(20, AZStd::get<0>(testVariant1).m_value);
- EXPECT_EQ(10, AZStd::get<0>(testVariant2).m_value);
- EXPECT_NE(0, AZStd::get<0>(testVariant1).m_moveAssignmentCounter);
- EXPECT_NE(0, AZStd::get<0>(testVariant2).m_moveAssignmentCounter);
- }
- }
- }
|