Post by j***@gmail.comThe programmer decides to start using `string_view` throughout his code
base. Because `string_view` doesn't convert to `string`, wherever he calls
`frobnicate`, *he has to add an explicit conversion* to `string`
I would have to say "good" at this point. My reasoning is as follows:
There seems to me to be a logical equivalence when creating a string_view
from a string. I.e. the string_view is a view of the string.
Creating a string from a string_view does not infer the same equivalence -
I think the correct term is that the operation is not associative. A.B is
not the same as B.A. This conversion actually constructs a new copy, not a
view or reference. It is a different kind of operation.
You are talking about commutativity. However, this concept can only be
applied to binary operations. A type conversion is not a binary operation;
it is a mapping.
If you want to establish a mathematical basis for type conversions, you
probably want to look at the concept of homomorphisms. A homomorphism is a
structure-preserving mapping between two algebraic structures of the same
type. For example, if you have a homomorphism, f : A -> B, that maps
structure A to structure B, it will preserve the operations. For example,
if A and B define addition then, given every pair of elements of A, x and y:
f(x + y) = f(x) + f(y)
If you apply this concept to the C++ type system, `A` and `B` are types
that meet the requirements of a shared concept, and the homomorphism `f` is
the conversion from `A` to `B`.
In our case, `string_view` and `string` are both conceptually "strings"
(they are the same kind of thing), and a conversion (homomorphism) does
exist from `string_view` to `string`, because the conversion maintains the
string operations (e.g. `length`, `substr`, `operator[]`, `operator+`). In
fact, a two-way conversion (isomorphism) between `string_view` and `string`
exists because `string` can also convert to `string_view` (which cannot be
said for other related pairs of types, like `int` and `short`).
Of course, exceptions throw a spanner in the works, because there is no
mathematical analogue (to my knowledge). I strongly believe that
conversions should be allowed to throw. This way, conversion can be allowed
for a partial mapping, f, where f(x) is undefined for some values of x (for
example, Robert Ramey's proposed Boost Safe Numerics library uses
exceptions like this to great effect, where for example, conversion from
`safe<long>` to `safe<short>` is permitted but may throw).
Conversion of value semantic types is a mathematical concept. Performance
concerns should not factor into the equation.
In my view, statement of intent of this copy should be explicit, as it has
side-effects. (i.e. the two objects are now unrelated).
`string_view` and `string` have value semantics. In other words:
string s = sv;
assert(s == sv);
They are not like pointers, where value is equivalent to the identity of
the underlying data. Two `string_view`s that internally reference the same
data are no more related than two `string`s of equal value. Equality is
what matters, not the underlying representation. The are no side effects.
Post by j***@gmail.comPost by Nicol BolasPost by j***@gmail.comIn my opinion, it the responsibility of the owner an object to be aware
of when potentially expensive copies are being made. The distinction
between implicit and explicit conversion should be made on the basis of
safety and correctness, not performance. Disallowing conversion from
`string_view` to `string` makes `string_view` awkward to use, which may
discourage people from using it -- a net loss in my view. The usability of
a type should not be hamstrung because of a fear that users might not aware
of the performance costs of certain operations.
A programmer who would genuinely give up using `string_view` in favor of
`std::string` just because it doesn't implicitly convert to `std::string`
is a programmer who doesn't *deserve* to have `string_view`. Providing
an explicit conversion requires minimal effort on the caller's part; it is
hardly sufficient reason to stop using a class.
This is typical "expert" mentality. Whether your users are the general
public or other programmers, if your product violates their expectations,
they will be reluctant to use it. Ignore your users at your own peril.
Post by Nicol BolasAnd furthermore, if you have so many conversions from `string_view` to
`std::string` that you encounter this problem frequently, you're using
`string_view` wrong. You aren't *supposed* to frequently convert them to
`std::string`s; they're for APIs where you don't need to modify the string.
Or maybe the user simply has requirements that do not align with your
expectations. I don't presume to know user requirements.
People use C++ because they want performance. We should do what we can to
Post by Nicol Bolasmake it hard for people to accidentally do slow things. The fast path
should be the default wherever possible, and to discourage the slow path,
we should
Performance is just one concern of many. Disallowing conversion from
`string_view` to `string` is not making the fast path the default; it is
disabling the default path because it has been deemed too slow. I have no
idea why this conversion has been singled out in this regard; consider the
string s;
string_view sv = s;
string s1 = s; // okay
string s2 = sv; // error
These operations do the *same* exact thing. Why is one allowed and the
other isn't? This is inconsistent. It makes no sense.
As another example of how requiring *explicit* conversion in this case is
wrong, consider a programmer who is using a 3rd party library with the
void frobnicate(std::string const& s);
The programmer decides to start using `string_view` throughout his code
base. Because `string_view` doesn't convert to `string`, wherever he
frobnicate(std::string(sv))
Unfortunately, this does have an impact on the performance of the user's
code. However, this cannot be helped because the 3rd party library cannot
be modified. At some point in the future, the programmer switches to a new
version of the 3rd party library, which has updated its interfaces to
support `string_view`. To avoid breaking user code, extra overloads of
void frobnicate(std::string const&);
void frobnicate(std::string_view);
void frobnicate(char const*);
Unfortunately, because the programmer is casting each `string_view` to a
`string` wherever he calls `frobnicate`, he experiences no performance
increase. If conversion from `string_view` to `string` *had* been
supported, this would not have been the case, and the performance of the
programmer's code would have returned to its pre-`string_view` state.
The problem here is that the explicit cast to `string` has suppressed the
type system, which has disabled the overload resolution mechanism which
would otherwise have chosen the most appropriate function to call. As I
said previously, if a conversion is correct and safe, it should be
implicit. Performance should *not* be a consideration.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at https://groups.google.com/a/is
ocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to a topic in the
Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this topic, visit https://groups.google.com/a/is
ocpp.org/d/topic/std-discussion/YVGIEJOt_E0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/is
ocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.