| Document number: | P0117R0 | 
| Date: | 2015-09-25 | 
| Project: | Programming Language C++, Library Evolution Working Group | 
| Reply-to: | Robert Kawulak <Robert Kawulak at gmail dot com> | 
to_string/to_wstring functionstemplate<class Ch, class Tr = char_traits<Ch>, class Alloc = allocator<Ch>, class... Args>
basic_string<Ch,Tr,Alloc> to_basic_string(Args&&... args)
{
    basic_ostringstream<Ch,Tr,Alloc> stream;
    stream.exceptions(ios_base::failbit | ios_base::badbit);
    stream << ... << forward<Args>(args);
    return stream.str();
}
template<class... Args>
string to_string(Args&&... args)
{
    return to_basic_string<char>(forward<Args>(args)...);
}
template<class... Args>
wstring to_wstring(Args&&... args)
{
    return to_basic_string<wchar_t>(forward<Args>(args)...);
}
For a long time C++ programmers have been looking for an easy way to convert an object into its string representation. A typical answer to this problem was to create a local ostringstream, insert the object into the stream, and then obtain the resulting string with the str member function. This solution is simple, safe, flexible and extensible, though definitely too verbose for something that rather ought to be a single function call. C++11 provided (a partial) solution in the form of a set of overloaded to_string/to_wstring functions. Unfortunately, these are limited only to the built-in numeric types. Non-standard solutions exist too – most notably boost::lexical_cast, which offers two-way conversion of objects and strings, but lacks any formatting control.
This paper proposes a solution that:
to_string/to_wstring functions for any type that provides a stream output operator and for any basic_string specialisation,ostringstream solution.int byte = 255;
to_string(hex, uppercase, byte); // format as an uppercase hexadecimal number: "FF"
int major = 4, minor = 11, revision = 2;
to_string(major, '.', minor, '.', revision); // yields "4.11.2"
int hours = 4, minutes = 9; bool afternoon = true;
to_string(hours, ':', setfill('0'), setw(2), minutes, afternoon ? " PM" : " AM"); // "4:09 PM"
cout << right << setfill('_') << setw(8) <<
    to_string(hours, ':', setfill('0'), setw(2), minutes); // "____4:09"
right, setfill('_') and setw(8) directives don't affect formatting of elements of "4:09" substring, but rather of the substring as a whole. Also, the setfill('0') and setw(2) directives have no effect outside of the substring generation.
        basic_string specialisationto_string and to_wstring function templates delegate the real work to a more generic to_basic_string function template. Calling the latter directly allows for customisation of the character type, traits and allocator used by the employed stream and the resulting string beyond the two default configurations provided by to_string and to_wstring.
        to_string/to_wstring overloads. 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&&)
"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:
to_str/to_wstr, format/wformat or stringize/wstringize,to_string/to_wstring functions supporting the existing behaviour, e.g.
string to_string(char c) { return to_string(static_cast<int>(c)); }to_string<>('0'),to_string()), yielding an empty string, should be explicitly disallowed. The author's opinion is no – this specialisation, even if lacking obvious use cases, is consistent with the general concept and there are no obvious disadvantages to keeping it. Also, providing such a somewhat artificial limitation could be potentially disruptive in generic code.
        ostringstream solution used under the hood by the proposed function templates is its relatively poor performance. However, in accordance with the “as if” rule, implementations are free to provide (and probably would benefit a lot from) optimisations for specific argument types, e.g. using sprintf directly just like the existing to_string/to_wstring functions or to preallocating the string's storage if maximum length of all the arguments can be determined upfront.