user2023370
user2023370

Reputation: 11037

Rvalue reference parameters and template functions

If I define a function which accepts an rvalue reference parameter:

template <typename T>
void fooT(T &&x) {}

I can call it, using GCC 4.5, with either a, ar, or arr:

int a, &ar = a, &&arr = 7;
fooT(a); fooT(ar); fooT(arr);

However, calling a similar, non-template function,

void fooInt(int &&x) {}

with any of those three arguments will fail. I was preparing to strengthen my knowledge of forward, but this has knocked me off course. Perhaps it's GCC 4.5; I was surprised to find that the first example from A Brief Introduction to Rvalue References also gives a compile error:

A a;
A&& a_ref2 = a;  // an rvalue reference

Upvotes: 9

Views: 4335

Answers (2)

Howard Hinnant
Howard Hinnant

Reputation: 218750

In addition to GMan's correct answer A Brief Introduction to Rvalue References has an incorrect example because it was written prior to a language change which outlawed:

A a;
A&& a_ref2 = a;  // an rvalue reference (DISALLOWED in C++11)

Despite this change in the language, the main uses cases described in the article (move and forward) are still explained correctly in the article.

Update: Oh, and the same article was originally published here with (imho) slightly better formatting.

Upvotes: 7

GManNickG
GManNickG

Reputation: 503855

The behavior of deduction in template parameters is unique, and is the reason your template version works. I've explained exactly how this deduction works here, in the context of another question.

Summarized: when the argument is an lvalue, T is deduced to T&, and T& && collapses to T&. And with the parameter at T&, it is perfectly valid to supply an lvalue T to it. Otherwise, T remains T, and the parameter is T&&, which accepts rvalues arguments.

Contrarily, int&& is always int&& (no template deduction rules to coerce it to something else), and can only bind to rvalues.

Upvotes: 13

Related Questions