C++ 用于打印枚举的模板化流运算符
我有一个名称空间,用于创建一系列枚举,这些枚举通过我的应用程序与相关的打印语句一起使用,如下所示:C++ 用于打印枚举的模板化流运算符,c++,templates,C++,Templates,我有一个名称空间,用于创建一系列枚举,这些枚举通过我的应用程序与相关的打印语句一起使用,如下所示: namespace NS { enum EnumA { A1, A2, A3 }; enum EnumB { B1, B2, B3 }; inline std::string toString(const EnumA key) { switch(key) { case A1: return "A1"; case A2: re
namespace NS {
enum EnumA { A1, A2, A3 };
enum EnumB { B1, B2, B3 };
inline std::string toString(const EnumA key) {
switch(key) {
case A1: return "A1";
case A2: return "A2";
case A3: return "A3";
}
return "UNKNOWN";
}
// .. same for EnumB
}
// this is the part I would like to templatize
inline std::ostream& operator<<(std::ostream& s, const NS::EnumA key) {
s << NS::toString(key);
return s;
}
inline std::ostream& operator<<(std::ostream& s, const NS::EnumB key) {
s << NS::toString(key);
return s;
}
显而易见的方法将导致您的过载被认为是所有类型;这将导致对所有类型的调用都不明确,因为模板是不可选择的。因此,您需要某种方法告诉编译器您的
enum
是正确的enum
类型,并忽略所有其他类型;traits类可能是最简单的方法
namespace NS {
enum EnumA { };
template<typename T>
struct is_ns_enum : std::false_type { };
template<>
struct is_ns_enum<EnumA> : std::true_type { };
}
NS{
enum EnumA{};
模板
结构是_ns_enum:std::false_type{};
模板
结构是_ns_enum:std::true_type{};
}
从那里,您可以使用SFINAE来实现您的功能
template<typename T>
inline typename std::enable_if<is_ns_enum<T>::value, std::ostream&>::type
operator <<(std::ostream& s, const T&) {
...
}
模板
内联类型名称std::enable_if::type
运算符如果您也对流类型进行模板化,这将起作用:
#include <string>
#include <iostream>
using namespace std;
namespace NS {
enum EnumA { A1, A2, A3 };
enum EnumB { B1, B2, B3 };
inline std::string toString(const EnumA key) {
switch(key) {
case A1: return "A1";
case A2: return "A2";
case A3: return "A3";
}
return "UNKNOWN";
}
inline std::string toString(const EnumB key) {
switch(key) {
case B1: return "B1";
case B2: return "B2";
case B3: return "B3";
}
return "UNKNOWN";
}
};
template <class Stream, typename T>
inline std::ostream& operator<<(Stream& s, T key) {
s << NS::toString(key);
return s;
}
int main()
{
cout << NS::A2;
cout << NS::B3;
}
#包括
#包括
使用名称空间std;
名称空间NS{
enum EnumA{A1,A2,A3};
enum EnumB{B1,B2,B3};
内联标准::字符串到字符串(常量枚举键){
开关(钥匙){
案例A1:返回“A1”;
案例A2:返回“A2”;
案例A3:返回“A3”;
}
返回“未知”;
}
内联标准::字符串到字符串(常量枚举键){
开关(钥匙){
案例B1:返回“B1”;
案例B2:返回“B2”;
案例B3:返回“B3”;
}
返回“未知”;
}
};
模板
内联std::ostream&operator如果名称空间NS
中只有支持toString的类型,您可以将运算符+1放在似乎有效的位置,但是,我最终编写了同样数量的代码,我总是忘记编写,因此需要一个模板。我不知道如何工作,但它确实有效,特别是因为直接打印到流不起作用(即使它在名称空间中)。
#include <string>
#include <iostream>
using namespace std;
namespace NS {
enum EnumA { A1, A2, A3 };
enum EnumB { B1, B2, B3 };
inline std::string toString(const EnumA key) {
switch(key) {
case A1: return "A1";
case A2: return "A2";
case A3: return "A3";
}
return "UNKNOWN";
}
inline std::string toString(const EnumB key) {
switch(key) {
case B1: return "B1";
case B2: return "B2";
case B3: return "B3";
}
return "UNKNOWN";
}
};
template <class Stream, typename T>
inline std::ostream& operator<<(Stream& s, T key) {
s << NS::toString(key);
return s;
}
int main()
{
cout << NS::A2;
cout << NS::B3;
}
namespace NS {
enum EnumA { A1, A2, A3 };
enum EnumB { B1, B2, B3 };
inline std::string toString(const EnumA key) {
...
}
inline std::string toString(const EnumB key) {
...
}
template <typename T>
inline std::ostream& operator<<(std::ostream& s, const T key) {
std::operator << (s, NS::toString(key));
return s;
}
}