1

For example, I have a code as below

template<class... Ts>
void f(Ts... args)
{
}

When passing the following arguments

int j = 5;
int& i = j;
f(i);

and

void g(int& i)
{
    f(i);
}

The captured types are int other than int& in both the above cases. How to let it capture int&, the same type as i? Thanks.

Constructor
  • 7,273
  • 2
  • 24
  • 66
user1899020
  • 13,167
  • 21
  • 79
  • 154

1 Answers1

4

Type template parameter deduction strips cv-qualifiers and ref-qualifers (It also converts array types to pointer types, and function types to function pointer types.)

If you want the reference to be part of the deduced type, add it to the declarator. (The same goes for const.)

template<class... Ts>
void f(Ts&... args);

If you want the deduced type to be either lvalue reference or rvalue reference depending on whether the argument is an lvalue or rvalue, use a "universal reference".

template<class... Ts>
void f(Ts&&... args);

(Despite what the latter looks like, it does not mean "accept rvalue only". This is much rarer. For this case, see How to make template rvalue reference parameter ONLY bind to rvalue reference?)

Note: There is no way to make a function that takes its argument by reference only if the variable passed in was declared as a reference. This is because a reference always behaves exactly like the object it refers to (except when decltype is applied).

Community
  • 1
  • 1
Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • I had a similar question... what if the function was called `template void f(int x, Ts&&... args)`? Would the parameters passed in `args` still be either lvalue or rvalue references or only rvalue references? – ssb Jun 24 '15 at 17:30