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

时间:2017-04-20 13:35:47

标签: c++ templates c++17

在使用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. 工作草案标准中的自动扣除指南在哪里?

1 个答案:

答案 0 :(得分:7)

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

  

形成一组功能和功能模板,包括:
   - 对于template-name指定的主类模板的每个构造函数,如果定义了模板,则具有以下属性的函数模板:
   - 模板参数是类模板的模板参数,后跟构造函数的模板参数(包括默认模板参数),如果有的话。
   - 函数参数的类型是构造函数的类型    - 返回类型是由模板名称和模板参数指定的类模板特化,对应于从类模板获取的模板参数。

我们的套装包括:

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]

  

转发参考是对cv非合格模板参数的右值引用,它不代表类模板的模板参数(在类模板参数推断期间[( over.match.class.deduct]))。如果P是转发引用且参数是左值,则使用类型“左值引用A”代替A来进行类型推导。

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

如果您希望类模板参数用作转发引用,则需要添加演绎指南:

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