diff options
Diffstat (limited to 'test/source/TestVariant.cpp')
-rw-r--r-- | test/source/TestVariant.cpp | 1823 |
1 files changed, 0 insertions, 1823 deletions
diff --git a/test/source/TestVariant.cpp b/test/source/TestVariant.cpp deleted file mode 100644 index 2a78a89..0000000 --- a/test/source/TestVariant.cpp +++ /dev/null @@ -1,1823 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Copyright (c) Electronic Arts Inc. All rights reserved. -///////////////////////////////////////////////////////////////////////////// - - -#include "EASTLTest.h" -#include <EASTL/string.h> -#include <EASTL/algorithm.h> -#include <EASTL/sort.h> -#include <EASTL/bonus/overloaded.h> - -#ifdef EA_COMPILER_CPP14_ENABLED -#include "ConceptImpls.h" -#include <EASTL/variant.h> - - -#if EASTL_EXCEPTIONS_ENABLED - -// Intentionally Non-Trivial. -// There are optimizations we can make in variant if the types are trivial that we don't currently do but can do. -template <typename T> -struct valueless_struct -{ - valueless_struct() {} - - valueless_struct(const valueless_struct&) {} - - ~valueless_struct() {} - - struct exception_tag {}; - - operator T() const { throw exception_tag{}; } -}; - -#endif - - -int TestVariantAlternative() -{ - using namespace eastl; - int nErrorCount = 0; - { - using v_t = variant<int>; - static_assert(is_same_v<variant_alternative_t<0, v_t>, int>, "error variant_alternative"); - } - { - using v_t = variant<int, long, short, char>; - - static_assert(is_same_v<variant_alternative_t<0, v_t>, int>, "error variant_alternative"); - static_assert(is_same_v<variant_alternative_t<1, v_t>, long>, "error variant_alternative"); - static_assert(is_same_v<variant_alternative_t<2, v_t>, short>, "error variant_alternative"); - static_assert(is_same_v<variant_alternative_t<3, v_t>, char>, "error variant_alternative"); - } - { - struct custom_type1 {}; - struct custom_type2 {}; - struct custom_type3 {}; - - using v_t = variant<int, long, short, char, size_t, unsigned, signed, custom_type1, custom_type2, custom_type3>; - - static_assert(is_same_v<variant_alternative_t<5, v_t>, unsigned>, "error variant_alternative"); - static_assert(is_same_v<variant_alternative_t<6, v_t>, signed>, "error variant_alternative"); - static_assert(is_same_v<variant_alternative_t<7, v_t>, custom_type1>, "error variant_alternative"); - static_assert(is_same_v<variant_alternative_t<8, v_t>, custom_type2>, "error variant_alternative"); - static_assert(is_same_v<variant_alternative_t<9, v_t>, custom_type3>, "error variant_alternative"); - } - // cv-qualifier tests - { - using v_t = variant<int, const int, volatile int, const volatile int>; - - static_assert(is_same_v<variant_alternative_t<0, v_t>, int>, "error variant_alternative"); - static_assert(is_same_v<variant_alternative_t<1, v_t>, const int>, "error variant_alternative"); - static_assert(is_same_v<variant_alternative_t<2, v_t>, volatile int>, "error variant_alternative"); - static_assert(is_same_v<variant_alternative_t<3, v_t>, const volatile int>, "error variant_alternative"); - } - return nErrorCount; -} - -int TestVariantSize() -{ - using namespace eastl; - int nErrorCount = 0; - - static_assert(variant_size<variant<int>>() == 1, "error variant_size"); - static_assert(variant_size<variant<int, int>>() == 2, "error variant_size"); - static_assert(variant_size<variant<int, int, int, int>>() == 4, "error variant_size"); - static_assert(variant_size<variant<const int>>() == 1, "error variant_size"); - static_assert(variant_size<variant<volatile int>>() == 1, "error variant_size"); - static_assert(variant_size<variant<const volatile int>>() == 1, "error variant_size"); - - static_assert(variant_size_v<variant<int>> == 1, "error variant_size"); - static_assert(variant_size_v<variant<int, int>> == 2, "error variant_size"); - static_assert(variant_size_v<variant<int, int, int, int>> == 4, "error variant_size"); - static_assert(variant_size_v<variant<const int>> == 1, "error variant_size"); - static_assert(variant_size_v<variant<volatile int>> == 1, "error variant_size"); - static_assert(variant_size_v<variant<const volatile int>> == 1, "error variant_size"); - - static_assert(variant_size_v<variant<int, int>> == 2, "error variant_size_v"); - static_assert(variant_size_v<variant<volatile int, const int>> == 2, "error variant_size_v"); - static_assert(variant_size_v<variant<volatile int, const int, const volatile int>> == 3, "error variant_size_v"); - - return nErrorCount; -} - -int TestVariantHash() -{ - using namespace eastl; - int nErrorCount = 0; - - { hash<monostate> h; EA_UNUSED(h); } - - return nErrorCount; -} - -int TestVariantBasic() -{ - using namespace eastl; - int nErrorCount = 0; - - { VERIFY(variant_npos == size_t(-1)); } - - { variant<int> v; EA_UNUSED(v); } - { variant<int, short> v; EA_UNUSED(v); } - { variant<int, short, float> v; EA_UNUSED(v); } - { variant<int, short, float, char> v; EA_UNUSED(v); } - { variant<int, short, float, char, long> v; EA_UNUSED(v); } - { variant<int, short, float, char, long, long long> v; EA_UNUSED(v); } - { variant<int, short, float, char, long, long long, double> v; EA_UNUSED(v); } - - { variant<monostate> v; EA_UNUSED(v); } - { variant<monostate, NotDefaultConstructible> v; EA_UNUSED(v); } - { variant<int, NotDefaultConstructible> v; EA_UNUSED(v); } - - { - struct MyObj - { - MyObj() : i(1337) {} - ~MyObj() {} - - int i; - }; - - struct MyObj2 - { - MyObj2(int& ii) : i(ii) {} - ~MyObj2() {} - - MyObj2& operator=(const MyObj2&) = delete; - - int& i; - }; - - static_assert(!eastl::is_trivially_destructible_v<MyObj>, "MyObj can't be trivially destructible"); - static_assert(!eastl::is_trivially_destructible_v<MyObj2>, "MyObj2 can't be trivially destructible"); - - { - eastl::variant<MyObj, MyObj2> myVar; - VERIFY(get<MyObj>(myVar).i == 1337); - } - - { - eastl::variant<MyObj, MyObj2> myVar = MyObj(); - VERIFY(get<MyObj>(myVar).i == 1337); - } - - { - int i = 42; - eastl::variant<MyObj, MyObj2> myVar = MyObj2(i); - VERIFY(get<MyObj2>(myVar).i == 42); - } - - { - auto m = MyObj(); - m.i = 2000; - - eastl::variant<MyObj, MyObj2> myVar = m; - VERIFY(get<MyObj>(myVar).i == 2000); - } - } - - { variant<int, int> v; EA_UNUSED(v); } - { variant<const short, volatile short, const volatile short> v; EA_UNUSED(v); } - { variant<int, int, const short, volatile short, const volatile short> v; EA_UNUSED(v); } - - { - // verify constructors and destructors are called - { - variant<TestObject> v = TestObject(1337); - VERIFY((get<TestObject>(v)).mX == 1337); - - variant<TestObject> vCopy = v; - VERIFY((get<TestObject>(vCopy)).mX == 1337); - } - VERIFY(TestObject::IsClear()); - TestObject::Reset(); - } - - { - variant<string> v; - VERIFY(*(get_if<string>(&v)) == ""); - VERIFY(get_if<string>(&v)->empty()); - VERIFY(get_if<string>(&v)->length() == 0); - VERIFY(get_if<string>(&v)->size() == 0); - - *(get_if<string>(&v)) += 'a'; - VERIFY(*(get_if<string>(&v)) == "a"); - } - - return nErrorCount; -} - -int TestVariantGet() -{ - using namespace eastl; - int nErrorCount = 0; - - { - const char* strValue = "canada"; - using v_t = variant<int, string>; - { - v_t v; - v = 42; - VERIFY(v.index() == 0); - VERIFY(*get_if<int>(&v) == 42); - VERIFY(get<int>(v) == 42); - VERIFY( holds_alternative<int>(v)); - VERIFY(!holds_alternative<string>(v)); - } - { - v_t v; - v = strValue; - VERIFY(v.index() == 1); - VERIFY(*get_if<string>(&v) == strValue); - VERIFY(get<string>(v) == strValue); - VERIFY(!holds_alternative<int>(v)); - VERIFY(holds_alternative<string>(v)); - VERIFY(get<string>(move(v)) == strValue); - } - { - v_t v; - v = 42; - VERIFY(v.index() == 0); - VERIFY(*get_if<0>(&v) == 42); - VERIFY(get<0>(v) == 42); - VERIFY( holds_alternative<int>(v)); - VERIFY(!holds_alternative<string>(v)); - } - { - v_t v; - v = strValue; - VERIFY(v.index() == 1); - VERIFY(*get_if<1>(&v) == strValue); - VERIFY(get<1>(v) == strValue); - VERIFY(!holds_alternative<int>(v)); - VERIFY( holds_alternative<string>(v)); - } - { - v_t v; - v = strValue; - VERIFY(v.index() == 1); - VERIFY(*get_if<1>(&v) == strValue); - VERIFY(get_if<0>(&v) == nullptr); - } - { - VERIFY(get_if<0>((v_t*)nullptr) == nullptr); - VERIFY(get_if<1>((v_t*)nullptr) == nullptr); - } - } - - return nErrorCount; -} - -int TestVariantHoldsAlternative() -{ - using namespace eastl; - int nErrorCount = 0; - - { - { - using v_t = variant<int, short>; // default construct first type - v_t v; - - VERIFY(!holds_alternative<long>(v)); // Verify that a query for a T not in the variant typelist returns false. - VERIFY(!holds_alternative<string>(v)); // Verify that a query for a T not in the variant typelist returns false. - VERIFY( holds_alternative<int>(v)); // variant does hold an int, because its a default constructible first parameter - VERIFY(!holds_alternative<short>(v)); // variant does not hold a short - } - - { - using v_t = variant<monostate, int, short>; // default construct monostate - v_t v; - - VERIFY(!holds_alternative<long>(v)); // Verify that a query for a T not in the variant typelist returns false. - VERIFY(!holds_alternative<string>(v)); // Verify that a query for a T not in the variant typelist returns false. - VERIFY(!holds_alternative<int>(v)); // variant does not hold an int - VERIFY(!holds_alternative<short>(v)); // variant does not hold a short - } - - { - using v_t = variant<monostate, int>; - - { - v_t v; - VERIFY(!holds_alternative<int>(v)); // variant does not hold an int - - v = 42; - VERIFY(holds_alternative<int>(v)); // variant does hold an int - } - - { - v_t v1, v2; - VERIFY(!holds_alternative<int>(v1)); - VERIFY(!holds_alternative<int>(v2)); - - v1 = 42; - VERIFY(holds_alternative<int>(v1)); - VERIFY(!holds_alternative<int>(v2)); - - eastl::swap(v1, v2); - VERIFY(!holds_alternative<int>(v1)); - VERIFY(holds_alternative<int>(v2)); - } - } - } - - return nErrorCount; -} - -int TestVariantValuelessByException() -{ - using namespace eastl; - int nErrorCount = 0; - - { - { - using v_t = variant<int, short>; - static_assert(eastl::is_default_constructible_v<v_t>, "valueless_by_exception error"); - - v_t v; - VERIFY(!v.valueless_by_exception()); - - v = 42; - VERIFY(!v.valueless_by_exception()); - } - - { - using v_t = variant<monostate, int>; - static_assert(eastl::is_default_constructible_v<v_t>, "valueless_by_exception error"); - - v_t v1, v2; - VERIFY(!v1.valueless_by_exception()); - VERIFY(!v2.valueless_by_exception()); - - v1 = 42; - VERIFY(!v1.valueless_by_exception()); - VERIFY(!v2.valueless_by_exception()); - - eastl::swap(v1, v2); - VERIFY(!v1.valueless_by_exception()); - VERIFY(!v2.valueless_by_exception()); - - v1 = v2; - VERIFY(!v1.valueless_by_exception()); - VERIFY(!v2.valueless_by_exception()); - } - - { - struct NotDefaultConstructibleButHasConversionCtor - { - NotDefaultConstructibleButHasConversionCtor() = delete; - NotDefaultConstructibleButHasConversionCtor(int) {} - }; - static_assert(!eastl::is_default_constructible<NotDefaultConstructibleButHasConversionCtor>::value, "valueless_by_exception error"); - - using v_t = variant<NotDefaultConstructibleButHasConversionCtor>; - v_t v(42); - static_assert(!eastl::is_default_constructible_v<v_t>, "valueless_by_exception error"); - VERIFY(!v.valueless_by_exception()); - } - - // TODO(rparolin): review exception safety for variant types - // - // { - // #if EASTL_EXCEPTIONS_ENABLED - // struct DefaultConstructibleButThrows - // { - // DefaultConstructibleButThrows() {} - // ~DefaultConstructibleButThrows() {} - // - // DefaultConstructibleButThrows(DefaultConstructibleButThrows&&) { throw 42; } - // DefaultConstructibleButThrows(const DefaultConstructibleButThrows&) { throw 42; } - // DefaultConstructibleButThrows& operator=(const DefaultConstructibleButThrows&) { throw 42; } - // DefaultConstructibleButThrows& operator=(DefaultConstructibleButThrows&&) { throw 42; } - // }; - // - // using v_t = variant<DefaultConstructibleButThrows>; - // - // v_t v1; - // VERIFY(!v1.valueless_by_exception()); - // - // try - // { - // v1 = DefaultConstructibleButThrows(); - // } - // catch (...) - // { - // VERIFY(v1.valueless_by_exception()); - // } - // #endif - // } - } - - return nErrorCount; -} - -int TestVariantCopyAndMove() -{ - using namespace eastl; - int nErrorCount = 0; - - { - { - using v_t = variant<int, short, char>; - - v_t v1 = 42; - v_t v2 = v1; - - VERIFY(get<int>(v2) == get<int>(v1)); - } - - } - - return nErrorCount; -} - -int TestVariantEmplace() -{ - using namespace eastl; - int nErrorCount = 0; - - { - variant<int> v; - v.emplace<int>(42); - VERIFY(get<int>(v) == 42); - } - { - variant<int> v; - v.emplace<0>(42); - VERIFY(get<0>(v) == 42); - } - - { - variant<int, short, long> v; - - v.emplace<0>(42); - VERIFY(get<0>(v) == 42); - - v.emplace<1>(short(43)); - VERIFY(get<1>(v) == short(43)); - - v.emplace<2>(44L); - VERIFY(get<2>(v) == 44L); - } - { - variant<int, short, long> v; - - v.emplace<int>(42); - VERIFY(get<int>(v) == 42); - - v.emplace<short>(short(43)); - VERIFY(get<short>(v) == short(43)); - - v.emplace<long>(44L); - VERIFY(get<long>(v) == 44L); - } - - { - { - variant<TestObject> v; - v.emplace<0>(1337); - VERIFY(get<0>(v).mX == 1337); - } - VERIFY(TestObject::IsClear()); - TestObject::Reset(); - } - - { - { - variant<int, TestObject> v; - - v.emplace<int>(42); - VERIFY(get<int>(v) == 42); - - v.emplace<TestObject>(1337); - VERIFY(get<TestObject>(v).mX == 1337); - - v.emplace<TestObject>(1338, 42, 3); - VERIFY(get<TestObject>(v).mX == 1338 + 42 + 3); - } - VERIFY(TestObject::IsClear()); - TestObject::Reset(); - } - - { - { - struct r { - r() = default; - r(int x) : mX(x) {} - int mX; - }; - - variant<int, r> v; - - v.emplace<0>(42); - VERIFY(get<0>(v) == 42); - - v.emplace<1>(1337); - VERIFY(get<1>(v).mX == 1337); - } - } - - { - struct r { - r() = default; - r(int a, int b, int c, int d) : a(a), b(b), c(c), d(d) {} - r(std::initializer_list<int> l) - { - auto it = l.begin(); - - a = *it++; - b = *it++; - c = *it++; - d = *it++; - } - int a, b, c, d; - }; - - r aa{1,2,3,4}; - VERIFY(aa.a == 1); - VERIFY(aa.b == 2); - VERIFY(aa.c == 3); - VERIFY(aa.d == 4); - - variant<r> v; - v.emplace<0>(std::initializer_list<int>{1,2,3,4}); - - VERIFY(get<r>(v).a == 1); - VERIFY(get<r>(v).b == 2); - VERIFY(get<r>(v).c == 3); - VERIFY(get<r>(v).d == 4); - } - - return nErrorCount; -} - -int TestVariantSwap() -{ - using namespace eastl; - int nErrorCount = 0; - - { - variant<int, float> v1 = 42; - variant<int, float> v2 = 24; - - v1.swap(v2); - - VERIFY(get<int>(v1) == 24); - VERIFY(get<int>(v2) == 42); - - v1.swap(v2); - - VERIFY(get<int>(v1) == 42); - VERIFY(get<int>(v2) == 24); - } - - { - variant<string> v1 = "Hello"; - variant<string> v2 = "World"; - - VERIFY(get<string>(v1) == "Hello"); - VERIFY(get<string>(v2) == "World"); - - v1.swap(v2); - - VERIFY(get<string>(v1) == "World"); - VERIFY(get<string>(v2) == "Hello"); - } - - return nErrorCount; -} - -int TestVariantRelOps() -{ - using namespace eastl; - int nErrorCount = 0; - - { - variant<int, float> v1 = 42; - variant<int, float> v2 = 24; - variant<int, float> v1e = v1; - - VERIFY(v1 == v1e); - VERIFY(v1 != v2); - VERIFY(v1 > v2); - VERIFY(v2 < v1); - } - - { - vector<variant<int, string>> v = {{1}, {3}, {7}, {4}, {0}, {5}, {2}, {6}, {8}}; - eastl::sort(v.begin(), v.end()); - VERIFY(eastl::is_sorted(v.begin(), v.end())); - } - - return nErrorCount; -} - - -int TestVariantInplaceCtors() -{ - using namespace eastl; - int nErrorCount = 0; - - { - variant<int, int> v(in_place<0>, 42); - VERIFY(get<0>(v) == 42); - VERIFY(v.index() == 0); - } - - { - variant<int, int> v(in_place<1>, 42); - VERIFY(get<1>(v) == 42); - VERIFY(v.index() == 1); - } - - { - variant<int, string> v(in_place<int>, 42); - VERIFY(get<0>(v) == 42); - VERIFY(v.index() == 0); - } - - { - variant<int, string> v(in_place<string>, "hello"); - VERIFY(get<1>(v) == "hello"); - VERIFY(v.index() == 1); - } - - return nErrorCount; -} - -// Many Compilers are smart and will fully inline the visitor in our unittests, -// Thereby not actually testing the recursive call. -EA_NO_INLINE int TestVariantVisitNoInline(const eastl::variant<int, bool, unsigned>& v) -{ - int nErrorCount = 0; - - bool bVisited = false; - - struct MyVisitor - { - MyVisitor() = delete; - MyVisitor(bool& visited) : mVisited(visited) {}; - - void operator()(int) { mVisited = true; } - void operator()(bool) { mVisited = true; } - void operator()(unsigned) { mVisited = true; } - - bool& mVisited; - }; - - eastl::visit(MyVisitor(bVisited), v); - - EATEST_VERIFY(bVisited); - - return nErrorCount; -} - -EA_NO_INLINE int TestVariantVisit2NoInline(const eastl::variant<int, bool>& v0, const eastl::variant<int, bool>& v1) -{ - int nErrorCount = 0; - - bool bVisited = false; - - struct MyVisitor - { - MyVisitor() = delete; - MyVisitor(bool& visited) : mVisited(visited) {}; - - void operator()(int, int) { mVisited = true; } - void operator()(bool, int) { mVisited = true; } - void operator()(int, bool) { mVisited = true; } - void operator()(bool, bool) { mVisited = true; } - - bool& mVisited; - }; - - eastl::visit(MyVisitor(bVisited), v0, v1); - - EATEST_VERIFY(bVisited); - - return nErrorCount; -} - -EA_NO_INLINE int TestVariantVisit3tNoInline(const eastl::variant<int, bool>& v0, const eastl::variant<int, bool>& v1, const eastl::variant<int, bool>& v2) -{ - int nErrorCount = 0; - - bool bVisited = false; - - struct MyVisitor - { - MyVisitor() = delete; - MyVisitor(bool& visited) : mVisited(visited) {}; - - void operator()(int, int, int) { mVisited = true; } - void operator()(bool, int, int) { mVisited = true; } - void operator()(int, bool, int) { mVisited = true; } - void operator()(bool, bool, int) { mVisited = true; } - - void operator()(int, int, bool) { mVisited = true; } - void operator()(bool, int, bool) { mVisited = true; } - void operator()(int, bool, bool) { mVisited = true; } - void operator()(bool, bool, bool) { mVisited = true; } - - bool& mVisited; - }; - - eastl::visit(MyVisitor(bVisited), v0, v1, v2); - - EATEST_VERIFY(bVisited); - - return nErrorCount; -} - -int TestVariantVisitorOverloaded() -{ - using namespace eastl; - int nErrorCount = 0; - - using v_t = variant<int, string, double, long>; - v_t arr[] = {42, "jean", 42.0, 42L}; - v_t v{42.0}; - - - #ifdef __cpp_deduction_guides - { - int count = 0; - - for (auto& e : arr) - { - eastl::visit( - overloaded{ - [&](int) { count++; }, - [&](string) { count++; }, - [&](double) { count++; }, - [&](long) { count++; }}, - e - ); - } - - VERIFY(count == EAArrayCount(arr)); - } - - { - double visitedValue = 0.0f; - - eastl::visit( - overloaded{ - [](int) { }, - [](string) { }, - [&](double d) { visitedValue = d; }, - [](long) { }}, - v - ); - - VERIFY(visitedValue == 42.0f); - } - - #endif - - { - int count = 0; - - for (auto& e : arr) - { - eastl::visit( - eastl::make_overloaded( - [&](int) { count++; }, - [&](string) { count++; }, - [&](double) { count++; }, - [&](long) { count++; }), - e - ); - } - - VERIFY(count == EAArrayCount(arr)); - } - - { - double visitedValue = 0.0f; - - eastl::visit( - eastl::make_overloaded( - [](int) { }, - [](string) { }, - [&](double d) { visitedValue = d; }, - [](long) { }), - v - ); - - VERIFY(visitedValue == 42.0f); - } - - return nErrorCount; -} - -int TestVariantVisitor() -{ - using namespace eastl; - int nErrorCount = 0; - - using v_t = variant<int, string, double, long>; - - { - v_t arr[] = {42, "hello", 42.0, 42L}; - - int count = 0; - for (auto& e : arr) - { - eastl::visit([&](auto){ count++; }, e); - } - - VERIFY(count == EAArrayCount(arr)); - - count = 0; - for (auto& e : arr) - { - eastl::visit<void>([&](auto){ count++; }, e); - } - - VERIFY(count == EAArrayCount(arr)); - } - - { - static bool bVisited = false; - - variant<int, long, string> v = 42; - - struct MyVisitor - { - void operator()(int) { bVisited = true; }; - void operator()(long) { }; - void operator()(string) { }; - void operator()(unsigned) { }; // not in variant - }; - - visit(MyVisitor{}, v); - VERIFY(bVisited); - - bVisited = false; - - visit<void>(MyVisitor{}, v); - VERIFY(bVisited); - } - - { - static bool bVisited = false; - - variant<int, bool, unsigned> v = (int)1; - - struct MyVisitor - { - bool& operator()(int) { return bVisited; } - bool& operator()(bool) { return bVisited; } - bool& operator()(unsigned) { return bVisited; } - }; - - bool& ret = visit(MyVisitor{}, v); - ret = true; - VERIFY(bVisited); - - bVisited = false; - bool& ret2 = visit<bool&>(MyVisitor{}, v); - ret2 = true; - VERIFY(bVisited); - } - - { - variant<int, bool, unsigned> v = (int)1; - - struct MyVisitor - { - void operator()(int& i) { i = 2; } - void operator()(bool&) {} - void operator()(unsigned&) {} - }; - - visit(MyVisitor{}, v); - EATEST_VERIFY(get<0>(v) == (int)2); - - v = (int)1; - visit<void>(MyVisitor{}, v); - EATEST_VERIFY(get<0>(v) == (int)2); - } - - { - static bool bVisited = false; - - variant<int, bool, unsigned> v =(int)1; - - struct MyVisitor - { - void operator()(const int&) { bVisited = true; } - void operator()(const bool&) {} - void operator()(const unsigned&) {} - }; - - visit(MyVisitor{}, v); - EATEST_VERIFY(bVisited); - - bVisited = false; - visit<void>(MyVisitor{}, v); - EATEST_VERIFY(bVisited); - } - - { - static bool bVisited = false; - - const variant<int, bool, unsigned> v =(int)1; - - struct MyVisitor - { - void operator()(const int&) { bVisited = true; } - void operator()(const bool&) {} - void operator()(const unsigned&) {} - }; - - visit(MyVisitor{}, v); - EATEST_VERIFY(bVisited); - - bVisited = false; - visit<void>(MyVisitor{}, v); - EATEST_VERIFY(bVisited); - } - - { - static bool bVisited = false; - - struct MyVisitor - { - void operator()(int&&) { bVisited = true; } - void operator()(bool&&) {} - void operator()(unsigned&&) {} - }; - - visit(MyVisitor{}, variant<int, bool, unsigned>{(int)1}); - EATEST_VERIFY(bVisited); - - visit<void>(MyVisitor{}, variant<int, bool, unsigned>{(int)1}); - EATEST_VERIFY(bVisited); - } - - { - static bool bVisited = false; - - variant<int, bool, unsigned> v = (int)1; - - struct MyVisitor - { - bool&& operator()(int) { return eastl::move(bVisited); } - bool&& operator()(bool) { return eastl::move(bVisited); } - bool&& operator()(unsigned) { return eastl::move(bVisited); } - }; - - bool&& ret = visit(MyVisitor{}, v); - ret = true; - VERIFY(bVisited); - - bVisited = false; - bool&& ret2 = visit<bool&&>(MyVisitor{}, v); - ret2 = true; - VERIFY(bVisited); - } - - { - variant<int, bool, unsigned> v = (int)1; - - TestVariantVisitNoInline(v); - v = (bool)true; - TestVariantVisitNoInline(v); - v = (int)3; - TestVariantVisitNoInline(v); - } - - { - variant<int, bool> v0 = (int)1; - variant<int, bool> v1 = (bool)true; - - TestVariantVisit2NoInline(v0, v1); - v0 = (bool)false; - TestVariantVisit2NoInline(v0, v1); - v1 = (int)2; - TestVariantVisit2NoInline(v0, v1); - } - - { - variant<int, bool> v0 = (int)1; - variant<int, bool> v1 = (int)2; - variant<int, bool> v2 = (int)3; - - TestVariantVisit3tNoInline(v0, v1, v2); - v2 = (bool)false; - TestVariantVisit3tNoInline(v0, v1, v2); - v0 = (bool)true; - TestVariantVisit3tNoInline(v0, v1, v2); - } - - { - static bool bVisited = false; - - variant<int, string> i = 42; - variant<int, string> s = "hello"; - - struct MultipleVisitor - { - MultipleVisitor& operator()(int, int) { return *this; } - MultipleVisitor& operator()(int, string) { bVisited = true; return *this; } - MultipleVisitor& operator()(string, int) { return *this; } - MultipleVisitor& operator()(string, string) { return *this; } - }; - - MultipleVisitor& ret = visit(MultipleVisitor{}, i, s); - EA_UNUSED(ret); - VERIFY(bVisited); - - MultipleVisitor& ret2 = visit<MultipleVisitor&>(MultipleVisitor{}, i, s); - EA_UNUSED(ret2); - VERIFY(bVisited); - } - - { - bool bVisited = false; - - variant<int, bool> v0 = 0; - variant<int, bool> v1 = 1; - - struct MultipleVisitor - { - MultipleVisitor() = delete; - MultipleVisitor(bool& visited) : mVisited(visited) {}; - - void operator()(int, int) { mVisited = true; } - void operator()(int, bool) {} - void operator()(bool, int) {} - void operator()(bool, bool) {} - - bool& mVisited; - }; - - visit(MultipleVisitor(bVisited), v0, v1); - EATEST_VERIFY(bVisited); - - bVisited = false; - visit<void>(MultipleVisitor(bVisited), v0, v1); - EATEST_VERIFY(bVisited); - } - - { - variant<int, string> v = 42; - - struct ModifyingVisitor - { - void operator()(int &i) { i += 1; } - void operator()(string &s) { s += "hello"; } - }; - - visit(ModifyingVisitor{}, v); - VERIFY(get<0>(v) == 43); - } - - { - variant<int, string> v = 42; - - struct ReturningVisitor - { - int operator()(int i) {return i;} - int operator()(string s) {return 0;} - }; - - VERIFY(visit(ReturningVisitor{}, v) == 42); - } - - return nErrorCount; -} - -int TestVariantVisitorReturn() -{ - int nErrorCount = 0; - - { - static bool bVisited = false; - - eastl::variant<int, bool> v = (int)1; - - struct MyVisitor - { - bool operator()(int) { bVisited = true; return true; } - bool operator()(bool) { return false; } - }; - - eastl::visit<void>(MyVisitor{}, v); - EATEST_VERIFY(bVisited); - } - - { - static bool bVisited = false; - - eastl::variant<int, bool> v = (int)1; - - struct MyVisitor - { - bool operator()(int) { bVisited = true; return true; } - bool operator()(bool) { return false; } - }; - - eastl::visit<const void>(MyVisitor{}, v); - EATEST_VERIFY(bVisited); - } - - { - static bool bVisited = false; - - eastl::variant<int, bool> v = (int)1; - - struct MyVisitor - { - bool operator()(int) { bVisited = true; return true; } - bool operator()(bool) { return false; } - }; - - eastl::visit<volatile void>(MyVisitor{}, v); - EATEST_VERIFY(bVisited); - } - - { - static bool bVisited = false; - - eastl::variant<int, bool> v = (int)1; - - struct MyVisitor - { - bool operator()(int) { bVisited = true; return true; } - bool operator()(bool) { return false; } - }; - - eastl::visit<const volatile void>(MyVisitor{}, v); - EATEST_VERIFY(bVisited); - } - - { - static bool bVisited = false; - - eastl::variant<int, bool> v = (int)1; - - struct MyVisitor - { - bool operator()(int) { bVisited = true; return true; } - bool operator()(bool) { return false; } - }; - - int ret = eastl::visit<int>(MyVisitor{}, v); - EATEST_VERIFY(bVisited); - EATEST_VERIFY(ret); - } - - { - static bool bVisited = false; - - struct A {}; - struct B : public A {}; - struct C : public A {}; - - eastl::variant<int, bool> v = (int)1; - - struct MyVisitor - { - B operator()(int) { bVisited = true; return B{}; } - C operator()(bool) { return C{}; } - }; - - A ret = eastl::visit<A>(MyVisitor{}, v); - EA_UNUSED(ret); - EATEST_VERIFY(bVisited); - } - - { - static bool bVisited = false; - - eastl::variant<int, bool> v = (int)1; - - struct MyVisitor - { - MyVisitor operator()(int) { bVisited = true; return MyVisitor{}; } - MyVisitor operator()(bool) { return MyVisitor{}; } - }; - - MyVisitor ret = eastl::visit<MyVisitor>(MyVisitor{}, v); - EA_UNUSED(ret); - EATEST_VERIFY(bVisited); - } - - return nErrorCount; -} - -int TestVariantAssignment() -{ - using namespace eastl; - int nErrorCount = 0; - - { - variant<int, TestObject> v = TestObject(1337); - VERIFY(get<TestObject>(v).mX == 1337); - TestObject::Reset(); - - v.operator=(42); // ensure assignment-operator is called - VERIFY(TestObject::sTODtorCount == 1); // verify TestObject dtor is called. - VERIFY(get<int>(v) == 42); - TestObject::Reset(); - } - - return nErrorCount; -} - - -int TestVariantMoveOnly() -{ - using namespace eastl; - int nErrorCount = 0; - - { - variant<int, MoveOnlyType> v = MoveOnlyType(1337); - VERIFY(get<MoveOnlyType>(v).mVal == 1337); - } - - return nErrorCount; -} - - -//compilation test related to PR #315: converting constructor and assignment operator compilation error -void TestCompilation(const double e) { eastl::variant<double> v{e}; } - - - -int TestVariantUserRegressionCopyMoveAssignmentOperatorLeak() -{ - using namespace eastl; - int nErrorCount = 0; - - { - { - eastl::variant<TestObject> v = TestObject(1337); - VERIFY(eastl::get<TestObject>(v).mX == 1337); - eastl::variant<TestObject> v2 = TestObject(1338); - VERIFY(eastl::get<TestObject>(v2).mX == 1338); - v.operator=(v2); - VERIFY(eastl::get<TestObject>(v).mX == 1338); - VERIFY(eastl::get<TestObject>(v2).mX == 1338); - } - VERIFY(TestObject::IsClear()); - TestObject::Reset(); - } - { - { - eastl::variant<TestObject> v = TestObject(1337); - VERIFY(eastl::get<TestObject>(v).mX == 1337); - eastl::variant<TestObject> v2 = TestObject(1338); - VERIFY(eastl::get<TestObject>(v2).mX == 1338); - v.operator=(eastl::move(v2)); - VERIFY(eastl::get<TestObject>(v).mX == 1338); - } - VERIFY(TestObject::IsClear()); - TestObject::Reset(); - } - { - { - eastl::variant<TestObject> v = TestObject(1337); - VERIFY(eastl::get<TestObject>(v).mX == 1337); - v = {}; - VERIFY(eastl::get<TestObject>(v).mX == 0); - } - VERIFY(TestObject::IsClear()); - TestObject::Reset(); - } - - return nErrorCount; -} - -int TestVariantRelationalOperators() -{ - int nErrorCount = 0; - - using VariantNoThrow = eastl::variant<int, bool, float>; - - // Equality - { - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ true }; - - EATEST_VERIFY((v1 == v2) == false); - } - - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ (int)1 }; - - EATEST_VERIFY((v1 == v2) == true); - } - - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ (int)0 }; - - EATEST_VERIFY((v1 == v2) == false); - } - } - - // Inequality - { - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ true }; - - EATEST_VERIFY((v1 != v2) == true); - } - - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ (int)1 }; - - EATEST_VERIFY((v1 != v2) == false); - } - - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ (int)0 }; - - EATEST_VERIFY((v1 != v2) == true); - } - } - - // Less Than - { - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ true }; - - EATEST_VERIFY((v1 < v2) == true); - } - - { - VariantNoThrow v1{ true }; - VariantNoThrow v2{ (int)1 }; - - EATEST_VERIFY((v1 < v2) == false); - } - - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ (int)1 }; - - EATEST_VERIFY((v1 < v2) == false); - } - - { - VariantNoThrow v1{ (int)0 }; - VariantNoThrow v2{ (int)1 }; - - EATEST_VERIFY((v1 < v2) == true); - } - } - - // Greater Than - { - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ true }; - - EATEST_VERIFY((v1 > v2) == false); - } - - { - VariantNoThrow v1{ true }; - VariantNoThrow v2{ (int)1 }; - - EATEST_VERIFY((v1 > v2) == true); - } - - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ (int)1 }; - - EATEST_VERIFY((v1 > v2) == false); - } - - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ (int)0 }; - - EATEST_VERIFY((v1 > v2) == true); - } - } - - // Less Equal - { - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ true }; - - EATEST_VERIFY((v1 <= v2) == true); - } - - { - VariantNoThrow v1{ true }; - VariantNoThrow v2{ (int)1 }; - - EATEST_VERIFY((v1 <= v2) == false); - } - - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ (int)1 }; - - EATEST_VERIFY((v1 <= v2) == true); - } - - { - VariantNoThrow v1{ (int)0 }; - VariantNoThrow v2{ (int)1 }; - - EATEST_VERIFY((v1 <= v2) == true); - } - - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ (int)0 }; - - EATEST_VERIFY((v1 <= v2) == false); - } - } - - // Greater Equal - { - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ true }; - - EATEST_VERIFY((v1 >= v2) == false); - } - - { - VariantNoThrow v1{ true }; - VariantNoThrow v2{ (int)1 }; - - EATEST_VERIFY((v1 >= v2) == true); - } - - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ (int)1 }; - - EATEST_VERIFY((v1 >= v2) == true); - } - - { - VariantNoThrow v1{ (int)0 }; - VariantNoThrow v2{ (int)1 }; - - EATEST_VERIFY((v1 >= v2) == false); - } - - { - VariantNoThrow v1{ (int)1 }; - VariantNoThrow v2{ (int)0 }; - - EATEST_VERIFY((v1 >= v2) == true); - } - } - -#if EASTL_EXCEPTIONS_ENABLED - - using VariantThrow = eastl::variant<int, bool, float>; - - auto make_variant_valueless = [](VariantThrow& v) - { - try - { - v.emplace<0>(valueless_struct<int>{}); - } - catch(const typename valueless_struct<int>::exception_tag &) - { - } - }; - - // Equality - { - { - VariantThrow v0{ (int)0 }; - VariantThrow v1{ (int)1 }; - - make_variant_valueless(v0); - make_variant_valueless(v1); - - EATEST_VERIFY((v0 == v1) == true); - } - } - - // Inequality - { - { - VariantThrow v0{ (int)0 }; - VariantThrow v1{ (int)1 }; - - make_variant_valueless(v0); - make_variant_valueless(v1); - - EATEST_VERIFY((v0 != v1) == false); - } - } - - // Less Than - { - { - VariantThrow v0{ (int)0 }; - VariantThrow v1{ (int)1 }; - - make_variant_valueless(v0); - - EATEST_VERIFY((v0 < v1) == true); - } - - { - VariantThrow v0{ (int)0 }; - VariantThrow v1{ (int)1 }; - - make_variant_valueless(v1); - - EATEST_VERIFY((v0 < v1) == false); - } - } - - // Greater Than - { - { - VariantThrow v0{ (int)1 }; - VariantThrow v1{ (int)0 }; - - make_variant_valueless(v0); - - EATEST_VERIFY((v0 > v1) == false); - } - - { - VariantThrow v0{ (int)1 }; - VariantThrow v1{ (int)0 }; - - make_variant_valueless(v1); - - EATEST_VERIFY((v0 > v1) == true); - } - } - - // Less Equal - { - { - VariantThrow v0{ (int)1 }; - VariantThrow v1{ (int)1 }; - - make_variant_valueless(v0); - - EATEST_VERIFY((v0 <= v1) == true); - } - - { - VariantThrow v0{ (int)1 }; - VariantThrow v1{ (int)0 }; - - make_variant_valueless(v1); - - EATEST_VERIFY((v0 <= v1) == false); - } - } - - // Greater Equal - { - { - VariantThrow v0{ (int)1 }; - VariantThrow v1{ (int)1 }; - - make_variant_valueless(v0); - - EATEST_VERIFY((v0 >= v1) == false); - } - - { - VariantThrow v0{ (int)1 }; - VariantThrow v1{ (int)0 }; - - make_variant_valueless(v1); - - EATEST_VERIFY((v0 >= v1) == true); - } - } - -#endif - - return nErrorCount; -} - - -int TestVariantUserRegressionIncompleteType() -{ - using namespace eastl; - int nErrorCount = 0; - - { - struct B; - - struct A - { - vector<variant<B>> v; - }; - - struct B - { - vector<variant<A>> v; - }; - } - - return nErrorCount; -} - -#define EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(Type, VarName) \ - bool operator==(const Type & rhs) const { return VarName == rhs.VarName; } \ - bool operator!=(const Type & rhs) const { return VarName != rhs.VarName; } \ - bool operator<(const Type & rhs) const { return VarName < rhs.VarName; } \ - bool operator>(const Type & rhs) const { return VarName > rhs.VarName; } \ - bool operator<=(const Type & rhs) const { return VarName <= rhs.VarName; } \ - bool operator>=(const Type & rhs) const { return VarName >= rhs.VarName; } - -int TestBigVariantComparison() -{ - int nErrorCount = 0; - - struct A; - struct B; - struct C; - struct D; - struct E; - struct F; - struct G; - struct H; - struct I; - struct J; - struct K; - struct L; - struct M; - struct N; - struct O; - struct P; - struct Q; - struct R; - struct S; - struct T; - struct U; - struct V; - struct W; - struct X; - struct Y; - struct Z; - - using BigVariant = eastl::variant<A, B, C, D, E, F, G, H, I, J, K, L, M, N, - O, P, Q, R, S, T, U, V, W, X, Y, Z>; - - struct A { int a; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(A, a) }; - struct B { int b; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(B, b) }; - struct C { int c; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(C, c) }; - struct D { int d; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(D, d) }; - struct E { int e; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(E, e) }; - struct F { int f; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(F, f) }; - struct G { int g; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(G, g) }; - struct H { int h; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(H, h) }; - struct I { int i; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(I, i) }; - struct J { int j; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(J, j) }; - struct K { int k; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(K, k) }; - struct L { int l; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(L, l) }; - struct M { int m; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(M, m) }; - struct N { int n; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(N, n) }; - struct O { int o; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(O, o) }; - struct P { int p; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(P, p) }; - struct Q { int q; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(Q, q) }; - struct R { int r; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(R, r) }; - struct S { int s; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(S, s) }; - struct T { int t; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(T, t) }; - struct U { int u; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(U, u) }; - struct V { int v; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(V, v) }; - struct W { int w; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(W, w) }; - struct X { int x; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(X, x) }; - struct Y { int y; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(Y, y) }; - struct Z { int z; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(Z, z) }; - - { - BigVariant v0{ A{0} }; - BigVariant v1{ A{1} }; - - VERIFY(v0 != v1); - } - - { - BigVariant v0{ A{0} }; - BigVariant v1{ A{1} }; - - VERIFY(v0 < v1); - } - - { - BigVariant v0{ A{0} }; - BigVariant v1{ A{0} }; - - VERIFY(v0 == v1); - } - - { - BigVariant v0{ A{1} }; - BigVariant v1{ A{0} }; - - VERIFY(v0 > v1); - } - - { - BigVariant v0{ A{0} }; - BigVariant v1{ A{1} }; - - VERIFY(v0 <= v1); - } - - { - BigVariant v0{ A{0} }; - BigVariant v1{ A{0} }; - - VERIFY(v0 <= v1); - } - - { - BigVariant v0{ A{0} }; - BigVariant v1{ A{0} }; - - VERIFY(v0 >= v1); - } - - { - BigVariant v0{ A{1} }; - BigVariant v1{ A{0} }; - - VERIFY(v0 >= v1); - } - - { - BigVariant v0{ A{0} }; - BigVariant v1{ B{0} }; - - VERIFY(v0 != v1); - } - - { - BigVariant v0{ A{0} }; - BigVariant v1{ B{0} }; - - VERIFY(v0 < v1); - } - - { - BigVariant v0{ A{0} }; - BigVariant v1{ B{0} }; - - VERIFY(v1 > v0); - } - - return nErrorCount; -} - -int TestVariantGeneratingComparisonOverloads(); - -int TestVariant() -{ - int nErrorCount = 0; - - nErrorCount += TestVariantBasic(); - nErrorCount += TestVariantSize(); - nErrorCount += TestVariantAlternative(); - nErrorCount += TestVariantValuelessByException(); - nErrorCount += TestVariantGet(); - nErrorCount += TestVariantHoldsAlternative(); - nErrorCount += TestVariantHash(); - nErrorCount += TestVariantCopyAndMove(); - nErrorCount += TestVariantSwap(); - nErrorCount += TestVariantEmplace(); - nErrorCount += TestVariantRelOps(); - nErrorCount += TestVariantInplaceCtors(); - nErrorCount += TestVariantVisitorOverloaded(); - nErrorCount += TestVariantVisitor(); - nErrorCount += TestVariantAssignment(); - nErrorCount += TestVariantMoveOnly(); - nErrorCount += TestVariantUserRegressionCopyMoveAssignmentOperatorLeak(); - nErrorCount += TestVariantUserRegressionIncompleteType(); - nErrorCount += TestVariantGeneratingComparisonOverloads(); - nErrorCount += TestBigVariantComparison(); - nErrorCount += TestVariantRelationalOperators(); - - return nErrorCount; -} -#else - int TestVariant() { return 0; } -#endif |