如何防止模板函数的隐式实例化

时间:2015-08-29 16:40:59

标签: c++ templates

我有一个包含几个强类型枚举的类,我希望它们可以隐式地与int相媲美。为此我编写了超简单的模板函数:

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

和相反的

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

然而,这可能是危险的,因为它几乎为T类和整数之间的任何比较写了一个空白检查。因此,我只想要几个明确指定的实例,例如

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

而不是其他。有没有办法禁用所有隐式实例化或实现这一点?当然,我总是可以为每个枚举分别编写两个运算符,但模板看起来确实是一个更好的解决方案。

1 个答案:

答案 0 :(得分:6)

<击> 使用SFINAE来拒绝不推导出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);

<击>

由于评论,我更新了我的答案。如果您只想接受少数几种模板类型,那么我建议使用这个bool_or技巧:

#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);

您可以添加任意数量的类型进行比较。