If I have a normal (weak) enumeration, I can use its enumerated values as non-type template parameters, like so:
enum { Cat, Dog, Horse };
template <int Val, typename T> bool magic(T &t)
{
return magical_traits<Val>::invoke(t);
}
and call it as: magic<Cat>(t)
as far as I can see, if I have a strongly-typed enumeration and don't want to hard-code the enumeration type, I end up with:
enum class Animal { Cat, Dog, Horse };
template <typename EnumClass, EnumClass EnumVal, typename T> bool magic(T &t)
{
return magical_traits<EnumVal>::invoke(t);
}
and now I have to write: magic<Animal, Animal::Cat>(t)
, which seems redundant.
Is there any way to avoid typing out both the enum class and the value, short of
#define MAGIC(E, T) (magic<decltype(E), E>(T));
You can do it like this, if you can use C++17
#include <type_traits>
enum class Animal { Cat, Dog, Horse };
template <typename EnumClass, EnumClass EnumVal>
void magic_impl()
{
static_assert(std::is_same_v<EnumClass, Animal>);
static_assert(EnumVal == Animal::Cat);
}
template <auto EnumVal>
void magic()
{
magic_impl<decltype(EnumVal), EnumVal>();
}
int main()
{
magic<Animal::Cat>();
}