c++ - 如何重载模板函数以用于枚举?

标签 c++ templates enums c++14

我有一堆函数,它们都具有相同的名称但具有不同的参数(其中一些是模板,一些不是):

void f(int& a) { ... } // there are a few other arithmetic types as well
void f(bool& a) { ... }
template <class T1, class T2> void f(std::pair<T1, T2>&a) { ... } 
template <class T> void f(T& a) { ... }
// ...

除此之外,我还有一个枚举:

enum MyEnum {
  enumVal1, enumVal2
};

我实际上认为,如果我现在调用 MyEnum e = enumVal1; f(e);,它会自动调用MyEnum底层类型的重载。它没有。相反,它会生成编译器错误。

现在我想定义一个模板函数来捕获所有枚举并调用适当的函数。

template <class T, std::enable_if_t<std::is_enum<T>{}> * = nullptr>
void f(T &a) { /* cast to std::underlying_type<T> and call f() */ }

不幸的是,出于某种原因,这会与现有的 f(T& a) 产生歧义。

我该如何解决这个问题?该解决方案必须对所有枚举都有效(但不适用于类枚举)。

我使用 gcc 4.9 和 clang 3.5 编译我的代码。

最佳答案

SFINAE 的使用并没有为部分排序提供更好的版本,而只是确定哪些重载可用。也就是说,对于枚举,f() 的两个同样好的候选函数导致了歧义。解决这种歧义的最简单方法是 SFINAE 两个候选者都是相互排斥的类型集:

template <class T, std::enable_if_t<!std::is_enum<T>{}> * = nullptr>
void f(T &a) {
    // version not applicable for enums
}
template <class T, std::enable_if_t<std::is_enum<T>{}> * = nullptr>
void f(T &a) {
    /* cast to std::underlying_type<T> and call f() */
}

不过,这不会解决您原来的问题,因为枚举数不是左值。请注意,您的原始问题可以通过T& 作为参数来解决,而是将 TT const& 或可能是 T&&:enumdo 转换为基础类型,但枚举器标记不是左值且无法绑定(bind)到非 const 引用。

除非有充分的理由不这样做,否则我可能只会使用一个重载:

template <typename T>
void f(T&& a) {
    // ...
}

关于c++ - 如何重载模板函数以用于枚举?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34107780/

相关文章:

c++ - 具有宽松内存顺序的 fetch_add 会返回唯一值吗?

c++ - 比较两个 IPv6 地址及其掩码 (windows)

c++ - 多个复制构造函数的编译器警告

java - 通过复制扩展 Enum

java - 为什么我收到 SPADE 无法解析为类型错误?

C++ 使用运算符重载构建双面树 - 什么是好的内存解决方案?

c++ - 当插入太多元素时,std::map 会自动调整大小吗?

c++ - 在类定义之外为模板类定义 operator[]()(数组订阅)

c++ - 何时使用 `static_assert` 而不是 SFINAE?

java - 枚举抽象问题