我有一堆函数,它们都具有相同的名称但具有不同的参数(其中一些是模板,一些不是):
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&
作为参数来解决,而是将 T
、T const&
或可能是 T&&
:enum
do 转换为基础类型,但枚举器标记不是左值且无法绑定(bind)到非 const
引用。
除非有充分的理由不这样做,否则我可能只会使用一个重载:
template <typename T>
void f(T&& a) {
// ...
}
关于c++ - 如何重载模板函数以用于枚举?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34107780/