简体   繁体   English

在具有通用引用参数的函数模板中使用类模板

[英]Using a class template in a function template with universal reference parameter

According to msvc, gcc and clang, the following code is illegal: 根据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 yields msvc收益率

xmemory0(591): error C2528: 'pointer': pointer to reference is illegal xmemory0(591):错误C2528:'指针':指向引用的指针是非法的

gcc and clang give similar sounding error messages. gcc和clang给出类似的声音错误消息。 Note that the universal reference parameter e is not used. 请注意,不使用通用参考参数e The compiler obviously fails to instantiate the vector v , complaining about it being used with a reference to int : 编译器显然无法实例化向量v ,抱怨它与int的引用一起使用:

note: see reference to class template instantiation 'std::vector<T,std::allocator<_Ty>>' being compiled with 注意:请参阅类模板实例化'std::vector<T,std::allocator<_Ty>>'的编译

  [ T=int &, _Ty=int & ] 

But I can't see where the function template f is instantiated with a reference to int . 但我无法看到函数模板f在何处通过对int的引用进行实例化。

Can somebody explain the compiler errors that we see here? 有人可以解释我们在这里看到的编译器错误吗?

When f is called with an lvalue int , T will be deduced as int& , so v will be a std::vector<int&> . 当使用左值int调用fT将推导为int& ,因此v将是std::vector<int&> This is invalid. 这是无效的。

One way to get around this is to remove references from T before using it: 解决此问题的一种方法是在使用之前从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 ...
}

However, if you want the function to be as generic as possible, you should use std::decay instead of std::remove_reference . 但是,如果您希望函数尽可能通用,则应使用std::decay而不是std::remove_reference This will let f work with cv-qualified types, arrays and functions. 这将使f与cv限定类型,数组和函数一起使用。

Scott Meyers explains in this article . Scott Meyers在本文中解释道。

If the expression initializing a universal reference is an lvalue, the universal reference becomes an lvalue reference. 如果初始化通用引用的表达式是左值,则通用引用将成为左值引用。

If the expression initializing the universal reference is an rvalue, the universal reference becomes an rvalue reference. 如果初始化通用引用的表达式是rvalue,则通用引用将成为右值引用。

In your case i is an lvalue and so T is deduced as int& . 在你的情况下, i是一个左值,因此T被推断为int&

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM