4

While testing C++17 deduction guide behaviour 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 have read from cpp reference, I thought v should be of type S<int &>. Nevertheless gcc7 does not compile this code complaining that a int& can not be bound to a int && (the universal reference mechanism fails).

So my questions are:

  1. Should gcc7 have deduced v to be of type S<int&>?

  2. Where are described automatic deduction guide in the working draft standard?

Oliv
  • 17,610
  • 1
  • 29
  • 72
  • 1
    Considering that GCC version 7 haven't been released yet, there are bound to be bugs. If this is one of them I don't know. Have you tried it with GCC 6 in C++17 mode (GCC 6 supports much of C++17)? – Some programmer dude Apr 20 '17 at 13:39
  • 1
    Deduction guide are not implemented in GCC6. I just want to know if it is cpp reference or GCC7 that is right, I cannot juge by myself because I do not find the entree in the standard... – Oliv Apr 20 '17 at 13:42
  • 2
    Note that cppreference does cover this case. It's the last example on that page. Cubbi and TC don't mess around :-) – Barry Apr 20 '17 at 13:53
  • Thank you, I have modifed the text to say that this is my understanding of cpp reference that is in cause and not directly cpp reference... This look like a tautology. – Oliv Apr 20 '17 at 13:58

1 Answers1

8

The rule in [over.match.class.deduct] is:

A set of functions and function templates is formed comprising:
- For each constructor of the primary class template designated by the template-name, if the template is defined, a function template with the following properties:
    - The template parameters are the template parameters of the class template followed by the template parameters (including default template arguments) of the constructor, if any.
    - The types of the function parameters are those of the constructor.
    - The return type is the class template specialization designated by the template-name and template arguments corresponding to the template parameters obtained from the class template.

Our set 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 perform overload resolution as usual, which involves template deduction. But from [temp.deduct.call]:

A forwarding reference is an rvalue reference to a cv-unqualified template parameter that does not represent a template parameter of a class template (during class template argument deduction ([over.match.class.deduct])). If P is a forwarding reference and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction.

Hence, this T&& is not a forwarding reference. It is an rvalue reference to T. So deduction against an lvalue (in our case, S(i)) fails. gcc is correct to reject your code here.

If you want the class template parameter to function as a forwarding reference, you will need to add a deduction guide:

template <class T> S(T&& ) -> S<T>;
Barry
  • 286,269
  • 29
  • 621
  • 977
  • Why does the deduction guide solve the issue? Doesn't `T` still represent a template parameter of a class template? Is there wording that defines what precisely `T` belongs to, here? Normally, I would take it to belong to the class template, like with a normal member function of a class template defined out of the class template body. I understand deduction guides are special beasts, so I'm asking whether there exist special rules? – Johannes Schaub - litb Apr 22 '17 at 18:49
  • 2
    @JohannesSchaub-litb In the deduction guide it's not a template parameter of a class template, it's a template parameter of a deduction guide. – Barry Apr 22 '17 at 18:51
  • @JohannesSchaub-litb I realize how that sounds. – Barry Apr 22 '17 at 18:54
  • I just read the specification and can confirm what you said. Thanks – Johannes Schaub - litb Apr 22 '17 at 19:03