#include #include #include #include #include #include #include #include using namespace android::pdx; using namespace android::pdx::rpc; namespace { struct BaseType { BaseType(int value) : value(value) {} int value; }; struct DerivedType : BaseType { DerivedType(int value) : BaseType{value} {}; }; template class TestType { public: TestType(const T& value) : value_(value) {} TestType(T&& value) : value_(std::move(value)) {} TestType(const TestType&) = default; TestType(TestType&&) = default; TestType& operator=(const TestType&) = default; TestType& operator=(TestType&&) = default; const T& get() const { return value_; } T&& take() { return std::move(value_); } private: T value_; }; template class InstrumentType { public: InstrumentType(const T& value) : value_(value) { constructor_count_++; } InstrumentType(T&& value) : value_(std::move(value)) { constructor_count_++; } InstrumentType(const InstrumentType& other) : value_(other.value_) { constructor_count_++; } InstrumentType(InstrumentType&& other) : value_(std::move(other.value_)) { constructor_count_++; } InstrumentType(const TestType& other) : value_(other.get()) { constructor_count_++; } InstrumentType(TestType&& other) : value_(other.take()) { constructor_count_++; } ~InstrumentType() { destructor_count_++; } InstrumentType& operator=(const InstrumentType& other) { copy_assignment_count_++; value_ = other.value_; return *this; } InstrumentType& operator=(InstrumentType&& other) { move_assignment_count_++; value_ = std::move(other.value_); return *this; } InstrumentType& operator=(const TestType& other) { copy_assignment_count_++; value_ = other.get(); return *this; } InstrumentType& operator=(TestType&& other) { move_assignment_count_++; value_ = other.take(); return *this; } static std::size_t constructor_count() { return constructor_count_; } static std::size_t destructor_count() { return destructor_count_; } static std::size_t move_assignment_count() { return move_assignment_count_; } static std::size_t copy_assignment_count() { return copy_assignment_count_; } const T& get() const { return value_; } T&& take() { return std::move(value_); } static void clear() { constructor_count_ = 0; destructor_count_ = 0; move_assignment_count_ = 0; copy_assignment_count_ = 0; } private: T value_; static std::size_t constructor_count_; static std::size_t destructor_count_; static std::size_t move_assignment_count_; static std::size_t copy_assignment_count_; }; template std::size_t InstrumentType::constructor_count_ = 0; template std::size_t InstrumentType::destructor_count_ = 0; template std::size_t InstrumentType::move_assignment_count_ = 0; template std::size_t InstrumentType::copy_assignment_count_ = 0; } // anonymous namespace TEST(Variant, Assignment) { // Assert basic type properties. { Variant v; ASSERT_EQ(-1, v.index()); ASSERT_FALSE(v.is()); ASSERT_FALSE(v.is()); ASSERT_FALSE(v.is()); } { Variant v; v = 10; ASSERT_EQ(0, v.index()); ASSERT_TRUE(v.is()); ASSERT_FALSE(v.is()); ASSERT_FALSE(v.is()); EXPECT_EQ(10, std::get(v)); } { Variant v; v = false; ASSERT_EQ(1, v.index()); ASSERT_FALSE(v.is()); ASSERT_TRUE(v.is()); ASSERT_FALSE(v.is()); EXPECT_EQ(false, std::get(v)); } { Variant v; v = 1.0f; ASSERT_EQ(2, v.index()); ASSERT_FALSE(v.is()); ASSERT_FALSE(v.is()); ASSERT_TRUE(v.is()); EXPECT_FLOAT_EQ(1.0f, std::get(v)); } { Variant v; // ERROR: More than one type is implicitly convertible from double. // v = 1.0; v = static_cast(1.0); } { Variant v; double x = 1.1; v = static_cast(x); ASSERT_EQ(2, v.index()); ASSERT_FALSE(v.is()); ASSERT_FALSE(v.is()); ASSERT_TRUE(v.is()); EXPECT_FLOAT_EQ(1.1, std::get(v)); } { Variant v; ASSERT_EQ(-1, v.index()); ASSERT_FALSE(v.is()); ASSERT_FALSE(v.is()); } { Variant v; v = 20; ASSERT_EQ(0, v.index()); ASSERT_TRUE(v.is()); ASSERT_FALSE(v.is()); EXPECT_EQ(20, std::get(v)); } { Variant v; v = std::string("test"); ASSERT_EQ(1, v.index()); ASSERT_FALSE(v.is()); ASSERT_TRUE(v.is()); EXPECT_EQ("test", std::get(v)); } { Variant v; v = "test"; ASSERT_EQ(1, v.index()); ASSERT_FALSE(v.is()); ASSERT_TRUE(v.is()); EXPECT_EQ("test", std::get(v)); } { Variant v1; Variant v2; v1 = "test"; ASSERT_TRUE(v1.is()); v2 = v1; ASSERT_TRUE(v2.is()); EXPECT_EQ("test", std::get(v2)); } { Variant a(1); Variant b; ASSERT_TRUE(!a.empty()); ASSERT_TRUE(b.empty()); a = b; ASSERT_TRUE(a.empty()); ASSERT_TRUE(b.empty()); } { Variant v; // ERROR: More than one type is implicitly convertible from nullptr. // v = nullptr; v = static_cast(nullptr); EXPECT_TRUE(v.is()); v = static_cast(nullptr); EXPECT_TRUE(v.is()); } { Variant v; int a = 10; char b = 20; v = &b; ASSERT_TRUE(v.is()); EXPECT_EQ(&b, std::get(v)); EXPECT_EQ(b, *std::get(v)); v = &a; ASSERT_TRUE(v.is()); EXPECT_EQ(&a, std::get(v)); EXPECT_EQ(a, *std::get(v)); } { using IntRef = std::reference_wrapper; Variant v; int a = 10; v = a; ASSERT_TRUE(v.is()); EXPECT_EQ(a, std::get(v)); a = 20; EXPECT_EQ(a, std::get(v)); } } TEST(Variant, MoveAssignment) { { Variant v; std::string s = "test"; v = std::move(s); EXPECT_TRUE(s.empty()); ASSERT_TRUE(v.is()); EXPECT_EQ("test", std::get(v)); } { Variant v("test"); std::string s = "fizz"; s = std::move(std::get(v)); ASSERT_TRUE(v.is()); EXPECT_TRUE(std::get(v).empty()); EXPECT_EQ("test", s); } { Variant a("test"); Variant b; b = std::move(a); ASSERT_TRUE(a.is()); ASSERT_TRUE(b.is()); EXPECT_TRUE(std::get(a).empty()); EXPECT_EQ("test", std::get(b)); } { Variant a("test"); Variant b("fizz"); b = std::move(a); ASSERT_TRUE(a.is()); ASSERT_TRUE(b.is()); EXPECT_TRUE(std::get(a).empty()); EXPECT_EQ("test", std::get(b)); } { Variant a("test"); Variant b(10); b = std::move(a); ASSERT_TRUE(a.is()); ASSERT_TRUE(b.is()); EXPECT_TRUE(std::get(a).empty()); EXPECT_EQ("test", std::get(b)); } { Variant a(10); Variant b("test"); b = std::move(a); ASSERT_TRUE(a.is()); ASSERT_TRUE(b.is()); EXPECT_EQ(10, std::get(a)); EXPECT_EQ(10, std::get(b)); } } TEST(Variant, Constructor) { { Variant v(true); EXPECT_TRUE(v.is()); } { Variant v(10); EXPECT_TRUE(v.is()); } { Variant v(10.1f); EXPECT_TRUE(v.is()); } { Variant v(10.); EXPECT_TRUE(v.is()); } { TestType i(1); Variant v(i.take()); ASSERT_TRUE(v.is()); EXPECT_EQ(1, std::get(v)); } { TestType i(1); Variant v(i.get()); ASSERT_TRUE(v.is()); EXPECT_EQ(1, std::get(v)); } { TestType b(true); Variant v(b.take()); ASSERT_TRUE(v.is()); EXPECT_EQ(true, std::get(v)); } { TestType b(true); Variant v(b.get()); ASSERT_TRUE(v.is()); EXPECT_EQ(true, std::get(v)); } { Variant c("test"); Variant s(c); ASSERT_TRUE(s.is()); EXPECT_EQ("test", std::get(s)); } { Variant a(true); Variant b(a); ASSERT_TRUE(b.is()); } { using IntRef = std::reference_wrapper; int a = 10; Variant v(a); TestType t(a); ASSERT_TRUE(v.is()); EXPECT_EQ(a, std::get(v)); EXPECT_EQ(a, t.get()); a = 20; EXPECT_EQ(a, std::get(v)); EXPECT_EQ(a, t.get()); } } // Verify correct ctor/dtor and assignment behavior used an instrumented type. TEST(Variant, CopyMoveConstructAssign) { { InstrumentType::clear(); // Default construct to empty, no InstrumentType activity. Variant> v; ASSERT_EQ(0u, InstrumentType::constructor_count()); ASSERT_EQ(0u, InstrumentType::destructor_count()); ASSERT_EQ(0u, InstrumentType::move_assignment_count()); ASSERT_EQ(0u, InstrumentType::copy_assignment_count()); } { InstrumentType::clear(); // Construct from int type, no InstrumentType activity. Variant> v; v = 10; EXPECT_EQ(0u, InstrumentType::constructor_count()); EXPECT_EQ(0u, InstrumentType::destructor_count()); EXPECT_EQ(0u, InstrumentType::move_assignment_count()); EXPECT_EQ(0u, InstrumentType::copy_assignment_count()); } { InstrumentType::clear(); // Construct from int type, no InstrumentType activity. Variant> v(10); EXPECT_EQ(0u, InstrumentType::constructor_count()); EXPECT_EQ(0u, InstrumentType::destructor_count()); EXPECT_EQ(0u, InstrumentType::move_assignment_count()); EXPECT_EQ(0u, InstrumentType::copy_assignment_count()); } { InstrumentType::clear(); // Construct from temporary, temporary ctor/dtor. Variant> v; v = InstrumentType(25); EXPECT_EQ(2u, InstrumentType::constructor_count()); EXPECT_EQ(1u, InstrumentType::destructor_count()); EXPECT_EQ(0u, InstrumentType::move_assignment_count()); EXPECT_EQ(0u, InstrumentType::copy_assignment_count()); } { InstrumentType::clear(); // Construct from temporary, temporary ctor/dtor. Variant> v(InstrumentType(25)); EXPECT_EQ(2u, InstrumentType::constructor_count()); EXPECT_EQ(1u, InstrumentType::destructor_count()); EXPECT_EQ(0u, InstrumentType::move_assignment_count()); EXPECT_EQ(0u, InstrumentType::copy_assignment_count()); } { InstrumentType::clear(); // Construct from temporary, temporary ctor/dtor. Variant> v(InstrumentType(25)); // Assign from temporary, temporary ctor/dtor. v = InstrumentType(35); EXPECT_EQ(3u, InstrumentType::constructor_count()); EXPECT_EQ(2u, InstrumentType::destructor_count()); EXPECT_EQ(1u, InstrumentType::move_assignment_count()); EXPECT_EQ(0u, InstrumentType::copy_assignment_count()); } { InstrumentType::clear(); // Construct from temporary, temporary ctor/dtor. Variant> v(InstrumentType(25)); // dtor. v = 10; EXPECT_EQ(2u, InstrumentType::constructor_count()); EXPECT_EQ(2u, InstrumentType::destructor_count()); EXPECT_EQ(0u, InstrumentType::move_assignment_count()); EXPECT_EQ(0u, InstrumentType::copy_assignment_count()); } { InstrumentType::clear(); // Construct from temporary, temporary ctor/dtor. Variant> v(InstrumentType(25)); EXPECT_EQ(2u, InstrumentType::constructor_count()); EXPECT_EQ(1u, InstrumentType::destructor_count()); EXPECT_EQ(0u, InstrumentType::move_assignment_count()); EXPECT_EQ(0u, InstrumentType::copy_assignment_count()); } EXPECT_EQ(2u, InstrumentType::constructor_count()); EXPECT_EQ(2u, InstrumentType::destructor_count()); EXPECT_EQ(0u, InstrumentType::move_assignment_count()); EXPECT_EQ(0u, InstrumentType::copy_assignment_count()); { InstrumentType::clear(); // Construct from other temporary. Variant> v(TestType(10)); EXPECT_EQ(1u, InstrumentType::constructor_count()); EXPECT_EQ(0u, InstrumentType::destructor_count()); EXPECT_EQ(0u, InstrumentType::move_assignment_count()); EXPECT_EQ(0u, InstrumentType::copy_assignment_count()); } { InstrumentType::clear(); // Construct from other temporary. Variant> v(TestType(10)); // Assign from other temporary. v = TestType(11); EXPECT_EQ(1u, InstrumentType::constructor_count()); EXPECT_EQ(0u, InstrumentType::destructor_count()); EXPECT_EQ(1u, InstrumentType::move_assignment_count()); EXPECT_EQ(0u, InstrumentType::copy_assignment_count()); } { InstrumentType::clear(); // Construct from other temporary. Variant> v(TestType(10)); // Assign from empty Variant. v = Variant>(); EXPECT_EQ(1u, InstrumentType::constructor_count()); EXPECT_EQ(1u, InstrumentType::destructor_count()); EXPECT_EQ(0u, InstrumentType::move_assignment_count()); EXPECT_EQ(0u, InstrumentType::copy_assignment_count()); } { InstrumentType::clear(); TestType other(10); // Construct from other. Variant> v(other); EXPECT_EQ(1u, InstrumentType::constructor_count()); EXPECT_EQ(0u, InstrumentType::destructor_count()); EXPECT_EQ(0u, InstrumentType::move_assignment_count()); EXPECT_EQ(0u, InstrumentType::copy_assignment_count()); } { InstrumentType::clear(); // Construct from other temporary. Variant> v(TestType(0)); TestType other(10); // Assign from other. v = other; EXPECT_EQ(1u, InstrumentType::constructor_count()); EXPECT_EQ(0u, InstrumentType::destructor_count()); EXPECT_EQ(0u, InstrumentType::move_assignment_count()); EXPECT_EQ(1u, InstrumentType::copy_assignment_count()); } { InstrumentType::clear(); // Construct from temporary, temporary ctor/dtor. Variant> v(InstrumentType(25)); // Assign EmptyVariant. v = EmptyVariant{}; EXPECT_EQ(2u, InstrumentType::constructor_count()); EXPECT_EQ(2u, InstrumentType::destructor_count()); EXPECT_EQ(0u, InstrumentType::move_assignment_count()); EXPECT_EQ(0u, InstrumentType::copy_assignment_count()); } EXPECT_EQ(2u, InstrumentType::constructor_count()); EXPECT_EQ(2u, InstrumentType::destructor_count()); EXPECT_EQ(0u, InstrumentType::move_assignment_count()); EXPECT_EQ(0u, InstrumentType::copy_assignment_count()); } TEST(Variant, MoveConstructor) { { std::unique_ptr pointer = std::make_unique(10); Variant> v(std::move(pointer)); ASSERT_TRUE(v.is>()); EXPECT_TRUE(std::get>(v) != nullptr); EXPECT_TRUE(pointer == nullptr); } { Variant> a(std::make_unique(10)); Variant> b(std::move(a)); ASSERT_TRUE(a.is>()); ASSERT_TRUE(b.is>()); EXPECT_TRUE(std::get>(a) == nullptr); EXPECT_TRUE(std::get>(b) != nullptr); } } TEST(Variant, IndexOf) { Variant v1; EXPECT_EQ(0, v1.index_of()); EXPECT_EQ(1, v1.index_of()); EXPECT_EQ(2, v1.index_of()); Variant v2; EXPECT_EQ(0, v2.index_of()); EXPECT_EQ(1, v2.index_of()); EXPECT_EQ(2, v2.index_of()); } struct Visitor { int int_value = 0; bool bool_value = false; float float_value = 0.0; bool empty_value = false; void Visit(int value) { int_value = value; } void Visit(bool value) { bool_value = value; } void Visit(float value) { float_value = value; } void Visit(EmptyVariant) { empty_value = true; } }; TEST(Variant, Visit) { { Variant v(10); EXPECT_TRUE(v.is()); Visitor visitor; v.Visit([&visitor](const auto& value) { visitor.Visit(value); }); EXPECT_EQ(10, visitor.int_value); visitor = {}; v = true; v.Visit([&visitor](const auto& value) { visitor.Visit(value); }); EXPECT_EQ(true, visitor.bool_value); } { Variant v; EXPECT_EQ(-1, v.index()); Visitor visitor; v.Visit([&visitor](const auto& value) { visitor.Visit(value); }); EXPECT_TRUE(visitor.empty_value); } { Variant v("test"); ASSERT_TRUE(v.is()); EXPECT_FALSE(std::get(v).empty()); v.Visit([](auto&& value) { std::remove_reference_t empty; std::swap(empty, value); }); ASSERT_TRUE(v.is()); EXPECT_TRUE(std::get(v).empty()); } } TEST(Variant, Become) { { Variant v; v.Become(0); EXPECT_TRUE(v.is()); v.Become(1); EXPECT_TRUE(v.is()); v.Become(2); EXPECT_TRUE(v.is()); v.Become(3); EXPECT_TRUE(v.empty()); v.Become(-1); EXPECT_TRUE(v.empty()); v.Become(-2); EXPECT_TRUE(v.empty()); } { Variant v; v.Become(0, 10); ASSERT_TRUE(v.is()); EXPECT_EQ(10, std::get(v)); v.Become(1, true); ASSERT_TRUE(v.is()); EXPECT_EQ(true, std::get(v)); v.Become(2, 2.0f); ASSERT_TRUE(v.is()); EXPECT_FLOAT_EQ(2.0f, std::get(v)); v.Become(3, 10); EXPECT_TRUE(v.empty()); v.Become(-1, 10); EXPECT_TRUE(v.empty()); v.Become(-2, 20); EXPECT_TRUE(v.empty()); } { Variant v; v.Become(0); ASSERT_TRUE(v.is()); EXPECT_TRUE(std::get(v).empty()); } { Variant v; v.Become(0, "test"); ASSERT_TRUE(v.is()); EXPECT_EQ("test", std::get(v)); } { Variant v("foo"); v.Become(0, "bar"); ASSERT_TRUE(v.is()); EXPECT_EQ("foo", std::get(v)); } } TEST(Variant, Swap) { { Variant a; Variant b; std::swap(a, b); EXPECT_TRUE(a.empty()); EXPECT_TRUE(b.empty()); } { Variant a("1"); Variant b; std::swap(a, b); EXPECT_TRUE(a.empty()); EXPECT_TRUE(!b.empty()); ASSERT_TRUE(b.is()); EXPECT_EQ("1", std::get(b)); } { Variant a; Variant b("1"); std::swap(a, b); EXPECT_TRUE(!a.empty()); EXPECT_TRUE(b.empty()); ASSERT_TRUE(a.is()); EXPECT_EQ("1", std::get(a)); } { Variant a("1"); Variant b("2"); std::swap(a, b); ASSERT_TRUE(a.is()); ASSERT_TRUE(b.is()); EXPECT_EQ("2", std::get(a)); EXPECT_EQ("1", std::get(b)); } { Variant a(10); Variant b("1"); std::swap(a, b); ASSERT_TRUE(a.is()); ASSERT_TRUE(b.is()); EXPECT_EQ("1", std::get(a)); EXPECT_EQ(10, std::get(b)); } { Variant a("1"); Variant b(10); std::swap(a, b); ASSERT_TRUE(a.is()); ASSERT_TRUE(b.is()); EXPECT_EQ(10, std::get(a)); EXPECT_EQ("1", std::get(b)); } } TEST(Variant, Get) { { Variant v; EXPECT_EQ(nullptr, &std::get(v)); EXPECT_EQ(nullptr, &std::get(v)); EXPECT_EQ(nullptr, &std::get(v)); EXPECT_EQ(nullptr, &std::get<0>(v)); EXPECT_EQ(nullptr, &std::get<1>(v)); EXPECT_EQ(nullptr, &std::get<2>(v)); EXPECT_EQ(nullptr, &std::get<3>(v)); } { Variant v; v = 9; ASSERT_TRUE(v.is()) << "Expected type " << v.index_of() << " got type " << v.index(); EXPECT_EQ(9, std::get(v)); EXPECT_EQ(9, std::get<0>(v)); std::get(v) = 10; EXPECT_EQ(10, std::get(v)); EXPECT_EQ(10, std::get<0>(v)); std::get<0>(v) = 11; EXPECT_EQ(11, std::get(v)); EXPECT_EQ(11, std::get<0>(v)); std::get<3>(v) = 12; EXPECT_EQ(12, std::get(v)); EXPECT_EQ(12, std::get<3>(v)); } { Variant v; v = false; ASSERT_TRUE(v.is()) << "Expected type " << v.index_of() << " got type " << v.index(); EXPECT_EQ(false, std::get(v)); EXPECT_EQ(false, std::get<1>(v)); std::get(v) = true; EXPECT_EQ(true, std::get(v)); EXPECT_EQ(true, std::get<1>(v)); std::get(v) = false; EXPECT_EQ(false, std::get(v)); EXPECT_EQ(false, std::get<1>(v)); std::get<1>(v) = true; EXPECT_EQ(true, std::get(v)); EXPECT_EQ(true, std::get<1>(v)); std::get<1>(v) = false; EXPECT_EQ(false, std::get(v)); EXPECT_EQ(false, std::get<1>(v)); } { Variant v; v = 1.0f; ASSERT_TRUE(v.is()) << "Expected type " << v.index_of() << " got type " << v.index(); EXPECT_EQ(2, v.index()); EXPECT_FLOAT_EQ(1.0, std::get(v)); EXPECT_FLOAT_EQ(1.0, std::get<2>(v)); std::get(v) = 1.1; EXPECT_FLOAT_EQ(1.1, std::get(v)); EXPECT_FLOAT_EQ(1.1, std::get<2>(v)); std::get(v) = -3.0; EXPECT_FLOAT_EQ(-3.0, std::get(v)); EXPECT_FLOAT_EQ(-3.0, std::get<2>(v)); std::get<2>(v) = 1.1; EXPECT_FLOAT_EQ(1.1, std::get(v)); EXPECT_FLOAT_EQ(1.1, std::get<2>(v)); std::get<2>(v) = -3.0; EXPECT_FLOAT_EQ(-3.0, std::get(v)); EXPECT_FLOAT_EQ(-3.0, std::get<2>(v)); } { Variant> v(std::make_unique(10)); std::unique_ptr pointer = std::move(std::get>(v)); ASSERT_FALSE(v.empty()); EXPECT_TRUE(pointer != nullptr); EXPECT_TRUE(std::get>(v) == nullptr); } { Variant v("test"); std::string s = std::get(std::move(v)); EXPECT_EQ("test", s); } } TEST(Variant, IfAnyOf) { { Variant v(10); ASSERT_TRUE(v.is()); bool b = false; EXPECT_TRUE(IfAnyOf::Get(&v, &b)); EXPECT_TRUE(b); float f = 0.0f; EXPECT_TRUE((IfAnyOf::Get(&v, &f))); EXPECT_FLOAT_EQ(10.f, f); } { const Variant v(10); ASSERT_TRUE(v.is()); bool b = false; EXPECT_TRUE(IfAnyOf::Get(&v, &b)); EXPECT_TRUE(b); float f = 0.0f; EXPECT_TRUE((IfAnyOf::Get(&v, &f))); EXPECT_FLOAT_EQ(10.f, f); } { Variant v(10); ASSERT_TRUE(v.is()); bool b = false; EXPECT_TRUE(IfAnyOf::Call(&v, [&b](const auto& value) { b = value; })); EXPECT_TRUE(b); float f = 0.0f; EXPECT_TRUE(( IfAnyOf::Call(&v, [&f](const auto& value) { f = value; }))); EXPECT_FLOAT_EQ(10.f, f); } { Variant, int> v(std::make_unique(10)); ASSERT_TRUE(v.is>()); const int* original_v = std::get>(v).get(); std::unique_ptr u(std::make_unique(20)); EXPECT_TRUE(IfAnyOf>::Take(&v, &u)); ASSERT_TRUE(v.is>()); EXPECT_TRUE(std::get>(v) == nullptr); EXPECT_EQ(u.get(), original_v); } { Variant, int> v( std::make_unique(10)); ASSERT_TRUE(v.is>()); const DerivedType* original_v = std::get>(v).get(); std::unique_ptr u(std::make_unique(20)); EXPECT_TRUE(IfAnyOf>::Take(&v, &u)); ASSERT_TRUE(v.is>()); EXPECT_TRUE(std::get>(v) == nullptr); EXPECT_EQ(u.get(), original_v); } { Variant, int> v(std::make_unique(10)); ASSERT_TRUE(v.is>()); const int* original_v = std::get>(v).get(); std::unique_ptr u(std::make_unique(20)); EXPECT_TRUE(IfAnyOf>::Call( &v, [&u](auto&& value) { u = std::move(value); })); ASSERT_TRUE(v.is>()); EXPECT_TRUE(std::get>(v) == nullptr); EXPECT_EQ(u.get(), original_v); } { Variant v(true); ASSERT_TRUE(v.is()); float f = 0.f; EXPECT_FALSE((IfAnyOf::Get(&v, &f))); EXPECT_FLOAT_EQ(0.f, f); } { Variant v("foo"); ASSERT_TRUE(v.is()); std::string s = "bar"; EXPECT_TRUE(IfAnyOf::Swap(&v, &s)); ASSERT_TRUE(v.is()); EXPECT_EQ("bar", std::get(v)); EXPECT_EQ("foo", s); } { Variant v(static_cast("foo")); ASSERT_TRUE(v.is()); std::string s = "bar"; EXPECT_TRUE((IfAnyOf::Take(&v, &s))); ASSERT_TRUE(v.is()); EXPECT_EQ("foo", std::get(v)); EXPECT_EQ("foo", s); v = std::string("bar"); ASSERT_TRUE(v.is()); EXPECT_TRUE((IfAnyOf::Take(&v, &s))); ASSERT_TRUE(v.is()); EXPECT_EQ("bar", s); } { Variant v; ASSERT_TRUE(v.empty()); std::string s = "bar"; EXPECT_FALSE((IfAnyOf::Take(&v, &s))); EXPECT_EQ("bar", s); } { Variant v(static_cast("test")); ASSERT_TRUE(v.is()); std::string s; EXPECT_FALSE(IfAnyOf<>::Take(&v, &s)); EXPECT_TRUE(s.empty()); } } TEST(Variant, ConstVolatile) { { Variant v(10); ASSERT_TRUE(v.is()); EXPECT_EQ(10, std::get(v)); } { Variant v("test"); ASSERT_TRUE(v.is()); EXPECT_EQ("test", std::get(v)); } { Variant v(10); ASSERT_TRUE(v.is()); EXPECT_EQ(10, std::get(v)); } } TEST(Variant, HasType) { EXPECT_TRUE((detail::HasType::value)); EXPECT_FALSE((detail::HasType::value)); EXPECT_FALSE(detail::HasType<>::value); EXPECT_TRUE((detail::HasType::value)); EXPECT_FALSE((detail::HasType::value)); } TEST(Variant, IsConstructible) { using ArrayType = const float[3]; struct ImplicitBool { operator bool() const { return true; } }; struct ExplicitBool { explicit operator bool() const { return true; } }; struct NonBool {}; struct TwoArgs { TwoArgs(int, bool) {} }; EXPECT_FALSE((detail::IsConstructible::value)); EXPECT_TRUE((detail::IsConstructible::value)); EXPECT_TRUE((detail::IsConstructible::value)); EXPECT_TRUE((detail::IsConstructible::value)); EXPECT_FALSE((detail::IsConstructible::value)); EXPECT_TRUE((detail::IsConstructible::value)); EXPECT_FALSE((detail::IsConstructible::value)); EXPECT_FALSE((detail::IsConstructible::value)); } TEST(Variant, Set) { EXPECT_TRUE((detail::Set::template IsSubset::value)); EXPECT_TRUE( (detail::Set::template IsSubset::value)); EXPECT_TRUE((detail::Set::template IsSubset::value)); EXPECT_TRUE((detail::Set::template IsSubset<>::value)); EXPECT_FALSE( (detail::Set::template IsSubset::value)); EXPECT_FALSE((detail::Set::template IsSubset::value)); EXPECT_FALSE( (detail::Set::template IsSubset::value)); EXPECT_FALSE((detail::Set::template IsSubset::value)); EXPECT_TRUE(detail::Set<>::template IsSubset<>::value); EXPECT_FALSE(detail::Set<>::template IsSubset::value); EXPECT_FALSE((detail::Set<>::template IsSubset::value)); }