模板 to_string << 运算符不适用于枚举 class
template to_string << operator does not work for enum class
我有一个 class 包裹了一个 std::map,我在下面对其进行了简化。我想实现一个 to_string() 函数,该函数使用运算符 <<
将第一个和第二个映射条目流式传输到字符串流中 - 然后 returns 字符串结果。
这适用于 int、float、string 等...基本上可以流式传输的任何内容。
但是enum class xzy : int {...};
不能流-或者必须先static_cast。但是在我的模板中,如果我将 static_cast 放在 x.second
周围,那么它将破坏其他模板类型。
我想知道如何处理这个问题。我的第一个想法是尝试使用类型特征来检测类型是否为整数(然后对其进行静态转换),否则仅依赖于正常的 operator <<
函数。
这里是 class:
template<typename T1, typename T2>
class map_wrapper
{
public:
std::map<T1, T2> m_map;
std::map<T1, T2> &map() {return m_map;}
std::string to_string()
{
std::stringstream ss;
for (const auto &item : m_map)
{
// <----------------------- ISSUE HERE
// So I want this to handle as many types as possible
// Maybe I can do some sort of if type traits == integral then static cast?
ss << item.first << ", " << static_cast<int>(item.second) << "\n";
//ss << item.first << ", " << item.second << "\n";
}
return ss.str();
}
};
这是我的测试代码:
enum class types : int
{
type1,
type2,
type3
};
int main()
{
// This is all ok
map_wrapper<int, int> int_map;
int_map.map() = {{1, 2}, {3, 4}};
std::cout << int_map.to_string() << std::endl;
// This only works if I static_cast the enum types to an int within to_string()
map_wrapper<int, types> type_map;
type_map.map() = {{1, types::type1}, {2, types::type2}};
std::cout << type_map.to_string() << std::endl;
return 0;
}
我已经注释了不能正常工作的部分。
实时可编辑示例:https://godbolt.org/z/rh8Y5v
更新
请注意枚举类型只是一个示例 - 我希望它能与任何枚举一起工作 class 理想情况下
您不能专门化单个成员函数,您需要专门化整个 class。如果你只是为了这个功能需要它,我建议提供一个模板运算符重载:
template<typename Enum,
typename = std::enable_if_t<std::is_enum_v<Enum>>>
std::ostream& operator<< (std::ostream& out, Enum e)
{
return out << static_cast<int>(e);
}
此运算符将接受任何 enum
或 enum class
。如果你只想接受 enum class
,你可以使用 C++23 中的 std::is_scoped_enum
或者推出你自己的(cppreference 中有一个可能的实现可以提供帮助)。
请注意,如果您想漂亮地打印特定枚举,您仍然可以提供重载(如果我们继续这样做,这将需要另一个完整的 class 专业化)。
我有一个 class 包裹了一个 std::map,我在下面对其进行了简化。我想实现一个 to_string() 函数,该函数使用运算符 <<
将第一个和第二个映射条目流式传输到字符串流中 - 然后 returns 字符串结果。
这适用于 int、float、string 等...基本上可以流式传输的任何内容。
但是enum class xzy : int {...};
不能流-或者必须先static_cast。但是在我的模板中,如果我将 static_cast 放在 x.second
周围,那么它将破坏其他模板类型。
我想知道如何处理这个问题。我的第一个想法是尝试使用类型特征来检测类型是否为整数(然后对其进行静态转换),否则仅依赖于正常的 operator <<
函数。
这里是 class:
template<typename T1, typename T2>
class map_wrapper
{
public:
std::map<T1, T2> m_map;
std::map<T1, T2> &map() {return m_map;}
std::string to_string()
{
std::stringstream ss;
for (const auto &item : m_map)
{
// <----------------------- ISSUE HERE
// So I want this to handle as many types as possible
// Maybe I can do some sort of if type traits == integral then static cast?
ss << item.first << ", " << static_cast<int>(item.second) << "\n";
//ss << item.first << ", " << item.second << "\n";
}
return ss.str();
}
};
这是我的测试代码:
enum class types : int
{
type1,
type2,
type3
};
int main()
{
// This is all ok
map_wrapper<int, int> int_map;
int_map.map() = {{1, 2}, {3, 4}};
std::cout << int_map.to_string() << std::endl;
// This only works if I static_cast the enum types to an int within to_string()
map_wrapper<int, types> type_map;
type_map.map() = {{1, types::type1}, {2, types::type2}};
std::cout << type_map.to_string() << std::endl;
return 0;
}
我已经注释了不能正常工作的部分。
实时可编辑示例:https://godbolt.org/z/rh8Y5v
更新
请注意枚举类型只是一个示例 - 我希望它能与任何枚举一起工作 class 理想情况下
您不能专门化单个成员函数,您需要专门化整个 class。如果你只是为了这个功能需要它,我建议提供一个模板运算符重载:
template<typename Enum,
typename = std::enable_if_t<std::is_enum_v<Enum>>>
std::ostream& operator<< (std::ostream& out, Enum e)
{
return out << static_cast<int>(e);
}
此运算符将接受任何 enum
或 enum class
。如果你只想接受 enum class
,你可以使用 C++23 中的 std::is_scoped_enum
或者推出你自己的(cppreference 中有一个可能的实现可以提供帮助)。
请注意,如果您想漂亮地打印特定枚举,您仍然可以提供重载(如果我们继续这样做,这将需要另一个完整的 class 专业化)。