2017-04-20 46 views
3

在测试与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已经推断vS<int&>类型的?

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

+1

考虑到GCC版本7都尚未公布,也一定会错误。如果这是其中之一,我不知道。你有没有在C++ 17模式下用GCC 6试过它(GCC 6支持C++ 17的大部分)? –

+1

扣除指南在GCC6中未实现。我只是想知道,如果它是cpp参考或GCC7是正确的,我不能自己juge,因为我没有找到标准的主题... – Oliv

+2

请注意,cppreference包括这种情况。这是该页面的最后一个例子。 Cubbi和TC不要乱搞:-) – Barry

回答

6

[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 

我们进行重载像往常一样,它涉及到的模板扣除。 但是[temp.deduct.call]

转发参考是一个rvalue参照CV-不合格模板参数不代表类模板参数推导期间一个类模板(的模板参数([在.match.class.deduct]))。如果P是转发引用并且参数是左值,则使用类型“左值引用A”来代替类型推导中的A.

因此,这是T&&转发参考。这是一个参考T的右值。因此,扣除左值(在本例中为S(i))失败。 gcc在这里拒绝你的代码是正确的。

如果你想在类模板参数用作转发引用,你将需要添加一个演绎指南:

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

为什么扣除指南可以解决问题?不'T'仍然代表一个类模板的模板参数?在这里,有什么措词定义了“T”属于哪个?通常情况下,我会将它归入类模板,就像使用类模板正文中定义的类模板的常规成员函数一样。我知道演绎指南是特别的野兽,所以我问是否有特殊的规则? –

+1

@ JohannesSchaub-litb在演绎指南中,它不是类模板的模板参数,它是演绎指南的模板参数。 – Barry

+0

@ JohannesSchaub-litb我意识到这听起来如何。 – Barry