Oli*_*liv 4 c++ templates c++17
在使用gcc7测试C++ 17演绎指导行为时,我发现此示例失败:
template<class T>
struct S{
S(T&& v){}
};
int i=10;
auto v = S(i);
Run Code Online (Sandbox Code Playgroud)
根据我从cpp引用中读到的内容,我认为v应该是类型S<int &>.然而gcc7没有编译这段代码抱怨a int&不能绑定到a int &&(通用引用机制失败).
所以我的问题是:
应该gcc7推断出v类型S<int&>?
工作草案标准中哪里描述了自动扣除指南?
[over.match.class.deduct]中的规则是:
形成一组函数和函数模板,包括:
- 对于由模板名称指定的主类模板的每个构造函数,如果定义了模板,则具有以下属性的函数模板:
- 模板参数是模板参数类模板后跟构造函数的模板参数(包括默认模板参数),如果有的话.
- 函数参数的类型是构造函数的类型.
- 返回类型是由模板名称和模板参数指定的类模板特化,对应于从类模板获得的模板参数.
我们的套装包括:
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
Run Code Online (Sandbox Code Playgroud)
我们像往常一样执行重载决策,这涉及模板推导.但是从[temp.deduct.call]:
甲转发参考是一个rvalue参照CV-不合格模板参数不代表一类模板的模板参数(类模板参数推导过程中([over.match.class.deduct])).如果P是转发引用且参数是左值,则使用类型"对A的左值引用"代替A来进行类型推导.
因此,这T&&是不转发参考.它是一个右值引用T.因此,对左值(在我们的例子中S(i))的推论失败了.gcc在这里拒绝您的代码是正确的.
如果您希望类模板参数用作转发引用,则需要添加演绎指南:
template <class T> S(T&& ) -> S<T>;
Run Code Online (Sandbox Code Playgroud)