diff --git a/include/asenum/asenum.h b/include/asenum/asenum.h index 5f957a7..84ff5d2 100644 --- a/include/asenum/asenum.h +++ b/include/asenum/asenum.h @@ -78,8 +78,23 @@ class name: protected asenum::impl::AsEnum #define ASENUM_DEFINE_STRUCTORS() \ -public: using AsEnum::type; \ -private: using AsEnum::AsEnum +private: \ + using AsEnum::AsEnum; \ + \ + template \ + struct AssociatedType { using Type = T; }; \ + \ + template \ + struct CaseCast; \ + \ +public: \ + template \ + const typename CaseCast::Type& as() const \ + { \ + return validatedValueOfType::Type>(t_type); \ + } \ + \ + using AsEnum::type /// For enums named in CamelCase style @@ -103,8 +118,11 @@ public: \ \ const type& as##case() const \ { \ - return *reinterpret_cast(validatedValueOfType(AssociatedEnum::case)); \ - } + return validatedValueOfType(AssociatedEnum::case); \ + } \ + \ + template <> \ + struct CaseCast : AssociatedType {} namespace asenum @@ -134,14 +152,15 @@ namespace asenum }) {} - const void* validatedValueOfType(const Enum type) const + template + const T& validatedValueOfType(const Enum type) const { if (m_type != type) { throw std::invalid_argument("Trying to get value of invalid type."); } - return m_value.get(); + return *reinterpret_cast(m_value.get()); } private: diff --git a/tests/AsEnumTest.cpp b/tests/AsEnumTest.cpp index e4d21ef..67d1762 100644 --- a/tests/AsEnumTest.cpp +++ b/tests/AsEnumTest.cpp @@ -49,26 +49,50 @@ namespace }; } -TEST(AssEnum, SimpleTest) +TEST(AssEnum, NamedGetter) { - const TestAsEnum value1 = TestAsEnum::CreateStringOpt("test"); - const TestAsEnum value2 = TestAsEnum::CreateBoolOpt(true); - const TestAsEnum value3 = TestAsEnum::CreateUnknown(-100500); - - EXPECT_EQ(value1.type(), TestEnum::StringOpt); - EXPECT_EQ(value2.type(), TestEnum::BoolOpt); - EXPECT_EQ(value3.type(), TestEnum::Unknown); - - EXPECT_EQ(value1.asStringOpt(), "test"); - EXPECT_THROW(value1.asUnknown(), std::exception); - EXPECT_THROW(value1.asBoolOpt(), std::exception); - - EXPECT_EQ(value2.asBoolOpt(), true); - EXPECT_THROW(value2.asUnknown(), std::exception); - EXPECT_THROW(value2.asStringOpt(), std::exception); - - EXPECT_EQ(value3.asUnknown(), -100500); - EXPECT_THROW(value3.asStringOpt(), std::exception); - EXPECT_THROW(value3.asBoolOpt(), std::exception); - + const TestAsEnum value1 = TestAsEnum::CreateStringOpt("test"); + const TestAsEnum value2 = TestAsEnum::CreateBoolOpt(true); + const TestAsEnum value3 = TestAsEnum::CreateUnknown(-100500); + + EXPECT_EQ(value1.type(), TestEnum::StringOpt); + EXPECT_EQ(value2.type(), TestEnum::BoolOpt); + EXPECT_EQ(value3.type(), TestEnum::Unknown); + + EXPECT_EQ(value1.asStringOpt(), "test"); + EXPECT_THROW(value1.asUnknown(), std::exception); + EXPECT_THROW(value1.asBoolOpt(), std::exception); + + EXPECT_EQ(value2.asBoolOpt(), true); + EXPECT_THROW(value2.asUnknown(), std::exception); + EXPECT_THROW(value2.asStringOpt(), std::exception); + + EXPECT_EQ(value3.asUnknown(), -100500); + EXPECT_THROW(value3.asStringOpt(), std::exception); + EXPECT_THROW(value3.asBoolOpt(), std::exception); + +} + +TEST(AssEnum, EnumGetter) +{ + const TestAsEnum value1 = TestAsEnum::CreateStringOpt("test"); + const TestAsEnum value2 = TestAsEnum::CreateBoolOpt(true); + const TestAsEnum value3 = TestAsEnum::CreateUnknown(-100500); + + EXPECT_EQ(value1.type(), TestEnum::StringOpt); + EXPECT_EQ(value2.type(), TestEnum::BoolOpt); + EXPECT_EQ(value3.type(), TestEnum::Unknown); + + EXPECT_EQ(value1.as(), "test"); + EXPECT_THROW(value1.as(), std::exception); + EXPECT_THROW(value1.as(), std::exception); + + EXPECT_EQ(value2.as(), true); + EXPECT_THROW(value2.as(), std::exception); + EXPECT_THROW(value2.as(), std::exception); + + EXPECT_EQ(value3.as(), -100500); + EXPECT_THROW(value3.as(), std::exception); + EXPECT_THROW(value3.as(), std::exception); + }