隐式模板推导指南可以推导引用类型吗?

Could an implicit template deduction guide deduce a reference type?

在用 gcc7 测试 C++17 推导指南行为时,我发现这个例子失败了:

template<class T>
struct S{
  S(T&& v){}
};
int i=10;
auto v = S(i);

根据我从 cpp reference 中读到的内容,我认为 v 应该是 S<int &> 类型。尽管如此,gcc7 不会编译此代码,抱怨 int& 不能绑定到 int &&(通用引用机制失败)。

所以我的问题是:

  1. gcc7 是否应该将 v 推导为 S<int&> 类型?

  2. 工作草案标准中哪里描述了自动扣除指南?

[over.match.class.deduct]中的规则是:

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.

我们的套装包括:

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

我们像往常一样执行重载决议,这涉及模板推导。 但是来自[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.

因此,此 T&& 不是 转发参考。它是对 T 的右值引用。因此,对左值(在我们的例子中,S(i))的推导失败了。 gcc 在这里拒绝您的代码是正确的。

如果想让class模板参数起到转发引用的作用,需要添加推导指南:

template <class T> S(T&& ) -> S<T>;