为通用枚举和其他类型重载模板函数
Overload template function for generic enum and the other types
我有一个适用于任何类型枚举的通用函数。我想用自定义 类 以及字符串和整数来重载它。但是,我会收到一条函数重载错误消息。我该如何解决?
error: call of overloaded 'show_value(MyAlpha)' is ambiguous
#include <type_traits>
#include <iostream>
#include <string>
using namespace std;
enum MyAlpha
{
ALPHA,
BETA
};
enum Animal
{
ELEFANT,
GOAT,
RABIT
};
class MyClass
{
public:
string text;
MyClass(string text): text(text) {}
};
template<typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
void show_value(T x) { cout<<"Enum: "<<(int)x<<endl; };
void show_value(int x) { cout<<"Int: "<<x<<endl; };
void show_value(string x) { cout<<"String: "<<x<<endl; };
template<class T>
void show_value(T x) { cout<<"Obj.text: "<<x.text<<endl; };
int main()
{
show_value(MyAlpha(BETA));
show_value(Animal(RABIT));
show_value(5);
show_value("Rainy day");
show_value(MyClass("Waterfall"));
return 0;
}
您应该使 SFINAE 的重载互斥 。否则,对于 enum
类型,两个模板化重载都是完全匹配的。
例如
template<typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
void show_value(T x) { cout<<"Enum: "<<(int)x<<endl; };
template<class T, typename std::enable_if<!std::is_enum<T>::value>::type* = nullptr>
void show_value(T x) { cout<<"Obj.text: "<<x.text<<endl; };
PS: "Rainy day"
不是 std::string
类型,而是 const char[]
类型。所以把show_value("Rainy day");
改成show_value(std::string("Rainy day"));
.
template<typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
void show_value(T x)
并不比(包罗万象)
更专业
template<class T> void show_value(T x);
所以用 enum
调用是不明确的。
对于非枚举,您必须放弃通用的:
template<typename T, typename std::enable_if<!std::is_enum<T>::value>::type* = nullptr>
void show_value(T x) { std::cout << "Obj.text: " << x.text << std::endl; };
或优先考虑。
struct low_priority_overload {};
struct high_priority_overload : low_priority_overload{};
// Or use template <std::size_t N> struct priority_overload : priority_overload<N - 1>{}
template<typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
void show_value_impl(high_priority_overload, T x) { cout<<"Enum: "<<(int)x<<endl; };
void show_value_impl(high_priority_overload, int x) { cout<<"Int: "<<x<<endl; };
void show_value_impl(high_priority_overload, string x) { cout<<"String: "<<x<<endl; };
template<class T>
void show_value_impl(low_priority_overload, T x) { cout<<"Obj.text: "<<x.text<<endl; };
template<class T>
void show_value(T x)
{
show_value_impl(high_priority_overload{}, x);
}
我有一个适用于任何类型枚举的通用函数。我想用自定义 类 以及字符串和整数来重载它。但是,我会收到一条函数重载错误消息。我该如何解决?
error: call of overloaded 'show_value(MyAlpha)' is ambiguous
#include <type_traits>
#include <iostream>
#include <string>
using namespace std;
enum MyAlpha
{
ALPHA,
BETA
};
enum Animal
{
ELEFANT,
GOAT,
RABIT
};
class MyClass
{
public:
string text;
MyClass(string text): text(text) {}
};
template<typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
void show_value(T x) { cout<<"Enum: "<<(int)x<<endl; };
void show_value(int x) { cout<<"Int: "<<x<<endl; };
void show_value(string x) { cout<<"String: "<<x<<endl; };
template<class T>
void show_value(T x) { cout<<"Obj.text: "<<x.text<<endl; };
int main()
{
show_value(MyAlpha(BETA));
show_value(Animal(RABIT));
show_value(5);
show_value("Rainy day");
show_value(MyClass("Waterfall"));
return 0;
}
您应该使 SFINAE 的重载互斥 。否则,对于 enum
类型,两个模板化重载都是完全匹配的。
例如
template<typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
void show_value(T x) { cout<<"Enum: "<<(int)x<<endl; };
template<class T, typename std::enable_if<!std::is_enum<T>::value>::type* = nullptr>
void show_value(T x) { cout<<"Obj.text: "<<x.text<<endl; };
PS: "Rainy day"
不是 std::string
类型,而是 const char[]
类型。所以把show_value("Rainy day");
改成show_value(std::string("Rainy day"));
.
template<typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
void show_value(T x)
并不比(包罗万象)
更专业template<class T> void show_value(T x);
所以用 enum
调用是不明确的。
对于非枚举,您必须放弃通用的:
template<typename T, typename std::enable_if<!std::is_enum<T>::value>::type* = nullptr>
void show_value(T x) { std::cout << "Obj.text: " << x.text << std::endl; };
或优先考虑。
struct low_priority_overload {};
struct high_priority_overload : low_priority_overload{};
// Or use template <std::size_t N> struct priority_overload : priority_overload<N - 1>{}
template<typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
void show_value_impl(high_priority_overload, T x) { cout<<"Enum: "<<(int)x<<endl; };
void show_value_impl(high_priority_overload, int x) { cout<<"Int: "<<x<<endl; };
void show_value_impl(high_priority_overload, string x) { cout<<"String: "<<x<<endl; };
template<class T>
void show_value_impl(low_priority_overload, T x) { cout<<"Obj.text: "<<x.text<<endl; };
template<class T>
void show_value(T x)
{
show_value_impl(high_priority_overload{}, x);
}