Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If rvalues did not bind to const references, how would this affect move semantics and perfect forwarding?

Tags:

c++

c++11

In http://www.reddit.com/r/IAmA/comments/1nl9at/i_am_a_member_of_facebooks_hhvm_team_a_c_and_d/ccjm2qs, Andrei Alexandrescu writes:

I think binding rvalues to const references has been the small mistake that caused the rvalue references Hindenburg... It would be a long discussion. Binding rvalues to const& made sense when first introduced (no templates, few subtleties) but in the long term made it virtually impossible to distinguish rvalues from lvalues on the callee side. That in turn forced an overly complex solution (rvalue references) as an expensive fix.

If the choice had not been made to bind rvalues to const references, how would this affect move semantics and perfect forwarding?

like image 264
Jon Avatar asked Nov 04 '13 05:11

Jon


People also ask

What is perfect forwarding?

What is Perfect Forwarding. Perfect forwarding allows a template function that accepts a set of arguments to forward these arguments to another function whilst retaining the lvalue or rvalue nature of the original function arguments.

What is the purpose of std :: forward?

std::forward helps to implement perfect forwarding. This mechanism implies that objects passed to the function as lvalue expressions should be copied, and objects passed to the function as rvalue expressions should be moved. If you assign an rvalue reference to some ref variable, then ref is a named entity.

What is a forwarding reference?

I understand that a forwarding reference is "an rvalue reference to a cv-unqualified template parameter", such as in. template <class T> void foo(T&& ); which means the above function can take both l-value and r-value reference.

What is the use of move semantics?

Move semantics aim to avoid the copying of data from temporary objects by instead stealing the memory location of where the object resides. This behaviour is implemented through the use of a move constructor and move assignment operator that act only on rvalue references.


1 Answers

I wasn't going to touch this question, considering it an extremely hypothetical question with not much value in answering. But I've changed my mind. There is value in answering this question that I did not previously comprehend.

Consider the common (not in C++, but in computer languages in general) API to split a string into an array of strings based on one or more delimiters. This ideally would return "string views" or "string_refs" into the original string to avoid copying pieces of the original string. A "string view" or "string_ref" is nothing but a pair of iterators into the original string. So something like:

vector<string_ref> split(const string& str, const string& delim);

With it known that vector<string_ref> refers back into str, it would be a bad idea for this function to bind to an rvalue. Once the client gets around to using the result, the reference into the argument would be long gone. The references would be dangling.

Thus it would be a good idea to forbid this function from accepting rvalue arguments for str, even though it is not going to modify this argument.

That being said, we have decades of experience that strongly indicate that this example is not typical. Most of the time, if a function isn't going to modify an argument, it does not matter if that argument is an rvalue or lvalue.

So if we had a clean sheet, it would make sense to make the common case be the easiest one to handle: rvalues can bind to const X&. But for cases like split, we need syntax for disallowing this common default behavior. How 'bout:

vector<string_ref> split(const string& str, const string& delim);
vector<string_ref> split(const string&& str, const string& delim) = delete;

I'm having trouble coming up with anything more elegant than this.

In other words: Usually, with the benefit of 20/20 hindsight, and lack of backwards compatibility constraints, one can do better with a redesign, given a clean sheet. But in this case, I've hypothesized myself a clean sheet, and I'm having trouble coming up with a better design than what we have.

<Disclaimer> I'm biased. </Disclaimer>

like image 53
Howard Hinnant Avatar answered Sep 19 '22 18:09

Howard Hinnant