Resurrection
Resurrection

Reputation: 4106

How to prevent implicit instantiation of a template function

I have a class with several strongly typed enums and I want them to be implicitly comparable to int. For that purpose I have written super-simple template function:

template<class T> bool operator==(const T &e, const int &i)
{
    return (static_cast<int>(e) == i);
}

and the opposite one

template<class T> bool operator==(const int &i, const T &e)
{
    return (e == i);
}

However this might be dangerous because it pretty much writes a blank check for any comparison between class T and an integer. I would therefore want only few explicitly specified instantiations such as

template bool operator==(const MyEnum &e, const int &i);
template bool operator==(const int &i, const MyEnum &e);

and no other. Is there a way to disable all implicit instantiations or achieve this? I can always write both operators for each enum separately of course but templates really seem like a better solution.

Upvotes: 1

Views: 719

Answers (1)

David G
David G

Reputation: 96875

Use SFINAE to reject overloads which don't deduce a MyEnum:

template<class T, std::enable_if_t<std::is_same<T, MyEnum>::value>* = nullptr>
bool operator==(const T &e, const int &i);

template<class T, std::enable_if_t<std::is_same<T, MyEnum>::value>* = nullptr>
bool operator==(const int &i, const T &e);


Due to the comments I have updated my answer. If you want to only accept select few template types then I suggest using this bool_or trick:

#include <type_traits>
#include <utility>

template<bool... Bs>
using bool_sequence = std::integer_sequence<bool, Bs...>;

template<bool... Bs>
using bool_and = std::is_same<bool_sequence<Bs...>,
                              bool_sequence<(Bs || true)...>>;

template<bool... Bs>
using bool_or = std::integral_constant<bool, !bool_and<!Bs...>::value>;

template<class T, class... Ts>
using any_same = bool_or<std::is_same<T, Ts>::value...>;

template<class T, std::enable_if_t<any_same<T, MyEnum, X, Y, Z>::value>* = nullptr>
bool operator==(const T &e, const int &i);

template<class T, std::enable_if_t<any_same<T, MyEnum, X, Y, Z>::value>* = nullptr>
bool operator==(const int &i, const T &e);

You can add any number of types to compare with.

Upvotes: 6

Related Questions