Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is overriding std::to_string for user defined enums the proper way to provide to_string for user defined enums?

C++ doesn't have a way to get the string representation of an enum. People get around this by writing custom functions that contain a lot of boilerplate code aka
switch with case XYZ return "XYZ";

That of course requires users of the enum to know the name of the custom function.

So I thought I could just add a specialization to std::to_string to enable a user to use to_string on my enums. Something like this:

//
#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;

}

Are there any problems with this solution?

like image 330
NoSenseEtAl Avatar asked Jun 16 '13 18:06

NoSenseEtAl


1 Answers

That's not "overriding" (which applies to virtual functions), and you haven't added a "specialization" (which applies to templates), you've added an overload, which adds a declaration and definition of a new function to namespace std and that's forbidden:

17.6.4.2.1 Namespace std [namespace.std]
The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.

A better solution would be to overload it in your own namespace, and call to_string(c) instead of std::to_string(c). That will find the right function and you don't need to add anything to std

like image 199
Jonathan Wakely Avatar answered Oct 15 '22 06:10

Jonathan Wakely