1

I have a large template definition (large as it overloads most of the operators) with which I have a problem when I need to specialize it for bool.

There is one example, although all the comparison operators are affected:

template<class T, T min, T max, T init_value = static_cast<T>(0)>
class limited_auto_enum_init
{
    ...snip...
    bool operator == (T v) const { return f_value == v; }
    bool operator == (bool v) const { return f_value == v; }
    ...snip...
};

As the name of the class implies, you are expected to make use of it when T comes from an enumeration. Since bool is generally viewed as an enumeration, I also want to instantiate a specialization for the bool type:

typedef limited_auto_enum_init<bool, false, true, false> flbool_t;
typedef limited_auto_enum_init<bool, false, true, true> tlbool_t;

When I do that, T is bool and therefore both functions have the exact same signature.

I looked into SFINAE and came up with something like this:

    template<class = typename std::enable_if<!std::is_fundamental<T>::value>::type>
    bool operator == (T v) const { return f_value == v; }

But for bool that tells me:

error: no type named ‘type’ in ‘struct std::enable_if’

For user enumerations it works fine.


Update:

I found a solution that works for me, as pointed out by @jrok (although the answer marked as the solution did not help me at all!). I had to define the return type of the other operator (the one explicitly taking a bool):

    template<class Q = T>
    typename std::enable_if<!std::is_fundamental<Q>::value, Q>::type
                         operator == (bool v) const { return f_value == v; }

That way the compiler (g++) is happy and fails as expected.

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
  • You can still keep your `bool` overload around with the SFINAE there. – chris Jun 06 '14 at 19:08
  • Since the code is the same, why do you even have two overloads here? – Ben Voigt Jun 06 '14 at 19:21
  • I was going to indicate this in an answer before it was prematurely marked a duplicate. In your case I expect moving your `operator==` external to the class will be a better approach than those mentioned in http://stackoverflow.com/questions/6972368/stdenable-if-to-conditionally-compile-a-member-function: `template ::value>::type > bool operator==(const Foo& f, const T& t) { ... }`, though Ben's point about identical code applies. – Michael Urman Jun 06 '14 at 19:23
  • @BenVoigt, they are the same only if T is bool. If it is an enumeration, then they clearly become different. You have to remember that it is necessary to overload each operator with all the fundamental types to match what C++ does with fundamental types when you create a template that is expected to represent a fundamental type... – Alexis Wilke Jun 06 '14 at 19:33
  • @Alexis: Why not use a template for that? `template bool operator==( const U& other ) { return f_value == v; }` – Ben Voigt Jun 06 '14 at 20:33

0 Answers0