Am 25.01.2017 23:55, schrieb Gavin Lambert:
On 26/01/2017 05:23, Christof Donat wrote:
to_string(x) is better than x.str() is better than implicit conversion.
Maybe it is just my strong distaste of the name to_string(), which at the moment is just a feeling, no good reasons. It just feels clumsy to me, while .str() is in line with regular expression matches, and stringstreams in the standard library.
Clumsy or not, it's in the standard now. [1]
Just as .str() is - in stringstream and in regular expression matches :-) The issue is, that the way, to_string() was explained, it seemed obvious to me, that it should not only be able to produce strings, but also e.g. wstrings. The original proposal was, to use a different name for every potential output: to_string(concat(...)); to_wstring(concat(...)); I'd prefer a more generic approach, because this does not give us much more possibilities than .str(). The worst proposal was to_utf8(), because then the string factories have to provide some representation, that can be converted to any character encoding later. I'd really prefer to set the character encoding on the string factory. Therefore I have another proposal: to<std::string>(concat(...)); to<std::wstring>(concat(...)); to<std::string>(concat(...).encoding(utf8)); to<std::string>(concat(...).encoding(latin1)); to<std::wstring>(concat(...).encoding(utf16)); to<std::string>(concat(...).encoding(utf16)); // error! to<std::vector<char>>(concat(...)); to<QString>(concat(...)); or alternatively: concat(...).to<std::string>(); concat(...).to<std::wstring>(); concat(...).encoding(utf8).to<std::string>(); concat(...).encoding(latin1).to<std::string>(); concat(...).encoding(utf16).to<std::wstring>(); concat(...).encoding(utf16).to<std::string>(); // error! concat(...).to<std::vector<char>>(); concat(...).to<QString>(); Both versions can have overloads, to reuse existing result values. In that case actually we don't need the template parameter, because it can be derived from the parameters type. to(s, concat(...)); to(ws, concat(...)); to(s, concat(...).encoding(utf8)); to(s, concat(...).encoding(latin1)); to(ws, concat(...).encoding(utf16)); to(v, concat(...)); to(qs, concat(...)); or: concat(...).to(s); concat(...).to(ws); concat(...).encoding(utf8).to(s); concat(...).encoding(latin1).to(s); concat(...).encoding(utf16).to(ws); concat(...).to(v); concat(...).to(qs); I prefer the second version. It reads like an english sentence. We can have the compiler check, that encoding(utf16) does not allow to<std::string>(). We just have to make sure, it returns a type, that only implements to() for wide character types.
str() is shorter, of course. I don't see any particular reason why you can't provide all of them, though (even the implicit conversion), as different things are going to feel more natural to different people, particularly in different contexts.
Yes. With the above proposal, we can easily implement all of them: class string_factory { public: // ... template<typename TargetType> auto to() -> TargetType {...}; template<typename TargetType> auto to(TargetType& t) -> TargetType& {...}; auto str() -> std::string { return to<std::string>() }; auto wstr() -> std::wstring { return to<std::wstring>() }; auto str(std::string& s) -> std::string& { return to<std::string>(s) }; auto wstr(std::wstring& ws) -> std::wstring &{ return to<std::wstring>(ws) }; operator std::string { return str(); }; operator std::wstring { return wstr(); }; } template <typename StringFactory> auto to_string(StringFactory& factory) -> std::string { return factory.str(); } template <typename StringFactory> auto to_wstring(StringFactory& factory) -> std::string { return factory.wstr(); } template <typename StringFactory> auto to_string(std::string& s, StringFactory& factory) -> std::string { return factory.str(s); } template <typename StringFactory> auto to_wstring(std::wstring& ws, StringFactory& factory) -> std::string { return factory.wstr(ws); } Christof