Search code examples
c++referencestandardslvaluetemplate-argument-deduction

Deducing LValue Reference type


There is quite a lot of discussion and clarification about template argument deduction and, in particular, reference collapsing and "universal references." This question goes through the relevant details: How does auto deduce type?, and this paper by Scott Meyers goes into even more detail and perhaps gives more examples and wider context: https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers, and his cppcon slides: http://www.aristeia.com/TalkNotes/C++TypeDeductionandWhyYouCareCppCon2014.pdf.
My question concerns the following code:

template <typename T> void f(T t) { t = 0; }

int main() {
  int i{5};
  int &ir{i};
  f(ir);
  cout << i << endl; // 5
  f<decltype(ir)>(ir);
  cout << i << endl; // 0
}

Why does my template function f not deduce they type int &? According to Scott Meyers' slides (slide 7) the fact that ir is lvalue reference is simply ignored. That perfectly explains this behavior, but to perfectly explain that I've spent some time reading the reference and standard trying to find where it says something like:

If A is a reference type, the referred type is used by deduction.

This is what an old, offline version of the reference says (that I typically use), although it said it under the header Conversion Function Template, and I haven't found this wording in the standard. The closes I've found I think came from the rules for partial ordering of overloaded templates, but I don't believe it would apply here, even it was what I was looking for.


Is there somewhere in the standard that this behavior is specified, or is it implied by other behavior that I've overlooked? I would really like to be able to tell someone "that doesn't deduce type int & because of these words in the standard right here."


Solution

  • There are no expressions of reference type in C++. The type of the variable ir is int&, but the type of the expression ir is int. This latter type is used for type deduction, since function arguments are always expressions (except in the special case of braced-init-lists).

    See [expr.type]/1

    If an expression initially has the type “reference to T” ([dcl.ref], [dcl.init.ref]), the type is adjusted to T prior to any further analysis. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression.