Boost logo

Boost :

Subject: Re: [boost] Variadic append for std::string
From: Christof Donat (cd_at_[hidden])
Date: 2017-01-26 07:21:16


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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk