隐式模板推导指南可以推导引用类型吗?
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 &&
(通用引用机制失败)。
所以我的问题是:
gcc7 是否应该将 v
推导为 S<int&>
类型?
工作草案标准中哪里描述了自动扣除指南?
[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>;
在用 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 &&
(通用引用机制失败)。
所以我的问题是:
gcc7 是否应该将
v
推导为S<int&>
类型?工作草案标准中哪里描述了自动扣除指南?
[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>;