But this is all a bit uglier at the call site, since either the library provides value-semantically-similar things with different names that either eat their arguments or copy-from-reference them, provides only the argument-eating version and relies on the caller to `clone` at their discretion, or provides only the referencing version and fails to elide copies.
In C++ you can provide a referencing version, and an argument-eating version with the same name that is called automatically when the user gives it a temporary or specifically requests it via `std::move`. Automatically eating temporaries is very nice in the case where the caller would like to compose a bunch of "create-new-from-a-set-of-references" operations in a single expression to create one new thing from an initial set of references.
The canonical example is eliding copies in stuff like
B*(A*x + b) + c
with overloaded * and + for vectors, since you really don't want to use something with a name other than + to request copy-elision. If you are one of those people who is grumpy about operator-overloading, you can imagine doing this with other "copy-some-refs-create-something" type functions, ... but actually you are probably grumpy about overloading those too.
In that case, eats_a_string() will allocate internally in the first and third cases, but it won't allocate in the second case, because the caller gives up ownership of its own allocated String. I wouldn't say this is a super common idiom, and "provide only the argument-eating version and rely on the caller to `clone` at their discretion" is often preferred to be simpler and more explicit. But you see it occasionally in the standard library, for example here: https://doc.rust-lang.org/std/ffi/struct.CString.html#method...
This sort of pattern tends to be more useful in case it's something like `CustomString` rather than just a regular `String`, and you still want your function/method to work with regular string literals. Also, other similar usecases, where there's a custom type that can be made from a standard type.
But this is all a bit uglier at the call site, since either the library provides value-semantically-similar things with different names that either eat their arguments or copy-from-reference them, provides only the argument-eating version and relies on the caller to `clone` at their discretion, or provides only the referencing version and fails to elide copies.
In C++ you can provide a referencing version, and an argument-eating version with the same name that is called automatically when the user gives it a temporary or specifically requests it via `std::move`. Automatically eating temporaries is very nice in the case where the caller would like to compose a bunch of "create-new-from-a-set-of-references" operations in a single expression to create one new thing from an initial set of references.
The canonical example is eliding copies in stuff like
with overloaded * and + for vectors, since you really don't want to use something with a name other than + to request copy-elision. If you are one of those people who is grumpy about operator-overloading, you can imagine doing this with other "copy-some-refs-create-something" type functions, ... but actually you are probably grumpy about overloading those too.