Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I just got to know that C++ has a std::to_string() defined in <string>. Now I wonder why to_string() only works with number types. Is there any particular reason, why there isnt a more general

template <typename T>
std::string to_string(const T& t);

?

Could be implemented like this:

template <typename T>
std::string to_string(const T& t) {
    std::ostringstream s;
    s << t;
    return s.str();
}

I suspect that such general to_string does not exist, because it is easy to write your own, but the same argument would apply to the to_string() taking int,double, etc.

like image 886
463035818_is_not_a_number Avatar asked Apr 13 '17 20:04

463035818_is_not_a_number


2 Answers

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.

like image 91
Hatted Rooster Avatar answered Oct 16 '22 21:10

Hatted Rooster


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.

like image 3
463035818_is_not_a_number Avatar answered Oct 16 '22 21:10

463035818_is_not_a_number