在具有通用引用参数

时间:2016-02-15 10:43:54

标签: c++ templates c++11 gcc

根据msvc,gcc和clang,以下代码是非法的:

template <typename T>
void f(T&& e) {
    std::vector<T> v;
    // do something with v and e ...
}
int main() {

    int i;
    f(i);
}

msvc产生

  

xmemory0(591):错误C2528:&#39;指针&#39;:指向引用的指针是   非法

gcc和clang给出类似的声音错误消息。请注意,不使用通用引用参数e。编译器显然无法实例化向量v,抱怨它与int的引用一起使用:

  

注意:请参阅类模板实例化的引用   正在编译'std::vector<T,std::allocator<_Ty>>'           与

    [
        T=int &,
        _Ty=int &
    ]

但我无法通过引用f来查看函数模板int的实例化。

有人可以解释我们在这里看到的编译器错误吗?

2 个答案:

答案 0 :(得分:18)

使用左值f调用int时,T将推断为int&,因此v将为std::vector<int&>。这是无效的。

解决此问题的一种方法是在使用前删除T中的引用:

template <typename T>
void f(T&& e) {
    using value_type = typename std::remove_reference<T>::type;
    //using value_type = std::remove_reference_t<T>; for C++14
    std::vector<value_type> v;
    // do something with v and e ...
}

但是,如果您希望该功能尽可能通用,则应使用std::decay代替std::remove_reference。这将允许f使用cv限定类型,数组和函数。

答案 1 :(得分:7)

Scott Meyers在此article中解释。

  

如果初始化通用引用的表达式是左值,则   通用引用成为左值引用。

     

如果表达   初始化通用引用是一个rvalue,通用   引用成为右值引用。

在您的情况下,i是左值,因此T推断为int&