Can the implicit template subtraction guideline infer a reference type?
While testing the behavior of the C ++ 17 deduction guide with gcc7, I found that this example fails:
template<class T>
struct S{
S(T&& v){}
};
int i=10;
auto v = S(i);
According to what I read from the cpp reference , I thought I v
should have a type S<int &>
. However, gcc7 does not compile this code, complaining that int&
it cannot be linked to int &&
(the universal link mechanism does not work).
So my questions are:
-
If gcc7 deduced
v
as a typeS<int&>
? -
Where is the manual for automatic deduction in the project working standard described?
source to share
Rule in [over.match.class.deduct] :
A set of functions and function templates has been created, containing:
- For each constructor of a primary class template assigned by the template name, if a template is defined, a function template with the following properties:
- template parameters are class template parameters followed by template parameters (including template arguments by default) constructor, if any.
- Function parameter types are constructor parameters.
- The return type is a specialization of the class template, denoted by template-name and template arguments corresponding to the template parameters obtained from the class template.
Our kit includes:
template <class T> // <-- the template parameters come from the class template
S<T> // <-- the return type is the class template specialization
foo(T&& ); // <-- the types of the parameters are those of the constructor
We do overload resolution as usual, which involves pattern subtraction. But from [temp.deduct.call] :
A forwarder reference is an rvalue reference to the cv-unqualified template parameter , which is not a class template template (when outputting a template template argument ([over.match.class.deduct])). If P is a forwarding reference and the argument is an lvalue, type "lvalue reference to A" is used for type inference instead of "A".
Hence, this one T&&
is not a forwarding link. This is the rvalue for T
. So deduction against lvalues (in our case S(i)
) fails. gcc correctly rejects your code here.
If you want a class template parameter to function as a forwarding reference, you will need to add a deduction guide:
template <class T> S(T&& ) -> S<T>;
source to share