Why there is only a `to_string()` for number types?

Because of the std::to_string() requirements.

As the standard states:

string to_string(int val);

string to_string(unsigned val);

string to_string(long val);

string to_string(unsigned long val);

string to_string(long long val);

string to_string(unsigned long long val);

string to_string(float val);

string to_string(double val);

string to_string(long double val);

Returns: Each function returns a string object holding the character representation of the value of its argument that would be generated by calling sprintf(buf, fmt, val) with a format specifier of "%d", "%u", "%ld", "%lu", "%lld", "%llu", "%f", "%f", or "%Lf", respectively, where buf designates an internal character buffer of sufficient size.

Writing a templated function that can determine the specifier that needs to be used for std::sprintf makes things unnecessarily complex.


Just want to add to Sombrero Chickens answer what I found in this proposal (thanks to @DAle for the link).

The proposal is about adding a generic to_string method. The principle would be the same as with my naive implementation: under the hood a stream is used to get a string from any object that can be streamed.

As the proposal came after c++11, adding such a method would have impact on the existing to_string and in the section "Impact on the standard" they write:

[...] The old and new functions could coexist, relying on the overload resolution to prefer a non-templated (existing) version in case of a matching argument type. However, a compatibility problem may arise in case of some distinct but implicitly convertible argument types:

to_string(0);     // before: calls to_string(int), now: calls to_string(int)
to_string(false); // before: calls to_string(int), now: calls to_string<bool>(bool&&)
to_string('0');   // before: calls to_string(int), now: calls to_string<char>(char&&)

While the effect is identical in the first two cases (the result is always "0"), in the last one the result will change from "48" (assuming ASCII encoding) to "0". There are several ways to deal with problematic specialisation cases like this one:

And then they list some options (including ignoring the problem) out of which none would be really satisfying.