0

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?

Roman
  • 1,396
  • 4
  • 15
  • 39
  • `std::enable_if_t` gives you a type, `void` by default. The above produces a type `bool`. The above compares a type against a boolean value `true`. The end result, what you have there is, basically `if (bool == true)`. As Mr. Spock would say: "This is not logical". – Sam Varshavchik Dec 10 '22 at 02:25
  • 1
    Your functions aren't specialisations they're overloads. Your two structs aren't specialisations either they're separate classes, you need to declare the base then specialise – Alan Birtles Dec 10 '22 at 02:26
  • If you have c++17 you can avoid the specialisations by using `if constexpr` instead – Alan Birtles Dec 10 '22 at 02:30

0 Answers0