Reputation: 33
can templates be specialized based on enum values
#include <type_traits>
template<typename T, typename = void>
struct Specialize
{
};
template<typename T>
struct Specialize<T, typename std::enable_if<std::is_enum<T>::value>::type>
{
void convert() { }
};
enum E
{
};
int main()
{
Specialize<E> spec;
spec.convert();
}
// My doubt: is below code valid? if not how to achieve this?
enum E
{
E1,
E2
};
int main()
{
Specialize<E, E1> spec;
spec.convert();
}
This is a follow-up question to the answer to the below question.
How can I partially specialize a class template for ALL enums?
I have copy pasted the code from the answer to the question linked above.
I am getting the following error with my changes.
error: type/value mismatch at argument 2 in template parameter list for _template<class T, class>
Upvotes: 2
Views: 425
Reputation: 66230
// My doubt: is below code valid?
Specialize<E, E1> spec;
Short answer: No.
Long answer.
You have defined Specialized
as a template struct
receiving two types template parameters
template<typename T, typename = void>
struct Specialize
{
};
E
is a type but E1
is a value.
if not how to achieve this?
If you want that your struct
/class
receive, as template parameters, a type and a value of that type, enabling the specialization of the struct
/class
iff (if and only if) the type is an enum, you have to add the typename = void
as third template parameter
template<typename T, T Val, typename = void>
struct Specialize
{
};
template<typename T, T Val>
struct Specialize<T, Val, typename std::enable_if<std::is_enum<T>::value>::type>
{
void convert() { }
};
Starting from C++17 you can also use auto
as type for the template value and remove the first template parameter
template<auto Val, typename = void>
struct Specialize
{
};
template<auto Val>
struct Specialize<Val, std::enable_if_t<std::is_enum_v<decltype(Val)>>>
{
void convert() { }
};
-- EDIT --
The OP asks
how would we define the function "convert" outside the struct/class?
Unfortunately I don't see a way, in this case, to avoid the std::enable_if
repetition
template <typename T, T Val>
struct Specialize<T, Val,
typename std::enable_if<std::is_enum<T>::value>::type>
{ void convert(); };
template <typename T, T Val>
void Specialize<T, Val,
typename std::enable_if<std::is_enum<T>::value>::type>::convert ()
{ };
Upvotes: 4
Reputation: 63402
Your compiler tells you that Specialize<E, E1> spec;
is invalid.
You can use std::integral_constant
to wrap a value in a type.
template<typename T, T V>
struct Specialize<std::integral_constant<T, V>, typename std::enable_if<std::is_enum<T>::value>::type>
{
void convert() { }
};
int main()
{
Specialize<std::integral_constant<E, E1>> spec;
spec.convert();
}
Upvotes: 2