Suppose I have a family of enums with predefined structure:
enum class A {BEGIN, a, b, c, END};
Now I need to implement a way to get min and max values (somewhat like numeric limits) which is able to work with both standard numeric types and enums.
If I write something like following chunk of code, I get desired result:
template <typename T, typename std::enable_if_t<std::is_enum_v<T>, bool> = true>
T min() {
return T::BEGIN;
}
template <typename T, typename std::enable_if_t<!std::is_enum_v<T>, bool> = true>
T min() {
return std::numeric_limits<T>::min();
}
...
min<A>(); // works
But shall I try to structure it a bit more, I immidiatelly get template redefinition errors:
template <typename T, typename std::enable_if_t<!std::is_enum_v<T>, bool> = true>
struct NumericLimits{
static T min() { return std::numeric_limits<T>::min(); }
static T max() { return std::numeric_limits<T>::max(); }
};
template <typename T, typename std::enable_if_t<std::is_enum_v<T>, bool> = true>
struct NumericLimits {
static T min() { return T::BEGIN; }
static T max() { return T::END; }
};
...
NumericLimits<A>::min(); // error
Compiler complais of following on call:
<source>:60:74: error: template non-type parameter has a different type 'typename std::enable_if_t<std::is_enum_v<T>, bool>' (aka 'typename enable_if<std::is_enum_v<T>, bool>::type') in template redeclaration
template <typename T, typename std::enable_if_t<std::is_enum_v<T>, bool> = true>
Although I kind of have what I want with the fist approach, I'm wondering what's wrong with second? I'd expect it to work too. Why am I unable to specialize class template? Or why function template specialization is not treated as redeclaration?