是否为用户定义的枚举重写std :: to_string是否为用户定义的枚举提供to_string的正确方法?

NoS*_*tAl 17 c++ enums tostring

C++没有办法获取枚举的字符串表示.人们解决这个问题通过编写又名含有大量的样板代码自定义函数
switchcase XYZ return "XYZ";

那当然要求枚举的用户知道自定义函数的名称.

所以我想我可以添加一个专门化std::to_string来让用户to_string在我的枚举上使用.像这样的东西:

//
#include <iostream>
#include <string>
#include <cassert>
#define TEST
class Car
{
public:
    enum class Color
    {
        Red,
        Blue,
        White
    };
};
#ifdef TEST
#include <string>
namespace std
{
    std::string to_string (Car::Color c)
    {
        switch (c)
        {
        case Car::Color::Red:
            return "Red";
        case Car::Color::Blue:
            return "Blue";
        case Car::Color::White:
            return "White";
        default:
            {
                assert(0);
                return "";
            }
        }
    }

}
#endif
int main()
{
    std::cout << std::to_string(Car::Color::White) << std::endl;

}
Run Code Online (Sandbox Code Playgroud)

这个解决方案有什么问题吗?

Jon*_*ely 22

这不是"覆盖"(适用于virtual函数),并且您没有添加"专门化"(适用于模板),您添加了一个重载,它将一个新函数的声明和定义添加到命名空间std,这是禁止:

17.6.4.2.1命名空间std [namespace.std]
如果C++程序向命名空间std或命名空间中的命名空间添加声明或定义,则它是未定义的,std除非另有说明.只有当声明取决于用户定义的类型并且特化符合原始模板的标准库要求且未明确禁止时,程序才可以将任何标准库模板的模板特化添加到命名空间std.

更好的解决方案是在您自己的命名空间中重载它,而to_string(c)不是调用std::to_string(c).这将找到正确的功能,你不需要添加任何东西std

  • 这是`使用std :: to_string`的好用之一.将你的`to_string`粘贴在你的`enum`的`namespace`中,如果使用`to_string`而没有`::`限定,adl会找到它.当您使用的类型是通用的时,只在本地范围内使用`using etd :: to_string` ... (5认同)
  • C++标准也考虑了函数的参数类型部分,它不仅仅是我:**1.3.17 [defns.signature]签名**<function>名称,参数类型列表(8.3.5)和封闭命名空间(如果有的话) ) (3认同)