Skip to content

Commit

Permalink
Added template merhod 'as<Type>'
Browse files Browse the repository at this point in the history
  • Loading branch information
Vladimir Vashurkin (Alkenso) committed Jul 23, 2019
1 parent 87da66b commit 9613e21
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 27 deletions.
31 changes: 25 additions & 6 deletions include/asenum/asenum.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,23 @@ class name: protected asenum::impl::AsEnum<enum, name>


#define ASENUM_DEFINE_STRUCTORS() \
public: using AsEnum::type; \
private: using AsEnum::AsEnum
private: \
using AsEnum::AsEnum; \
\
template <typename T> \
struct AssociatedType { using Type = T; }; \
\
template <AssociatedEnum t_type> \
struct CaseCast; \
\
public: \
template <AssociatedEnum t_type> \
const typename CaseCast<t_type>::Type& as() const \
{ \
return validatedValueOfType<typename CaseCast<t_type>::Type>(t_type); \
} \
\
using AsEnum::type


/// For enums named in CamelCase style
Expand All @@ -103,8 +118,11 @@ public: \
\
const type& as##case() const \
{ \
return *reinterpret_cast<const type*>(validatedValueOfType(AssociatedEnum::case)); \
}
return validatedValueOfType<type>(AssociatedEnum::case); \
} \
\
template <> \
struct CaseCast<AssociatedEnum::case> : AssociatedType<type> {}


namespace asenum
Expand Down Expand Up @@ -134,14 +152,15 @@ namespace asenum
})
{}

const void* validatedValueOfType(const Enum type) const
template <typename T>
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<const T*>(m_value.get());
}

private:
Expand Down
66 changes: 45 additions & 21 deletions tests/AsEnumTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<TestEnum::StringOpt>(), "test");
EXPECT_THROW(value1.as<TestEnum::Unknown>(), std::exception);
EXPECT_THROW(value1.as<TestEnum::BoolOpt>(), std::exception);

EXPECT_EQ(value2.as<TestEnum::BoolOpt>(), true);
EXPECT_THROW(value2.as<TestEnum::Unknown>(), std::exception);
EXPECT_THROW(value2.as<TestEnum::StringOpt>(), std::exception);

EXPECT_EQ(value3.as<TestEnum::Unknown>(), -100500);
EXPECT_THROW(value3.as<TestEnum::StringOpt>(), std::exception);
EXPECT_THROW(value3.as<TestEnum::BoolOpt>(), std::exception);

}

0 comments on commit 9613e21

Please sign in to comment.