templates之为什么在 C++0x 中,编译器选择通用移动赋值而不是特定移动赋值

mengfanrong 阅读:16 2024-11-24 20:56:43 评论:0

我有以下代码:

#include <iostream> 
using namespace std; 
 
template <class T> class Foo { 
public: 
    template <class U> void operator = (const U &u) { 
        cout << "generic copy assigment\n"; 
    } 
 
    void operator = (const Foo<T> &f) { 
        cout << "specific copy assigment\n"; 
    } 
 
    template <class U> void operator = (U &&u) { 
        cout << "generic move assigment\n"; 
    } 
 
    void operator = (Foo<T> &&f) { 
        cout << "specific move assigment\n"; 
    } 
}; 
 
int main() { 
    Foo<int> i, j; 
    i = j; 
    return 0; 
} 

如果运行,它会打印“通用移动分配”,即编译器更喜欢移动而不是副本。但是,如果我注释掉两个移动分配:

template <class T> class Foo { 
public: 
    template <class U> void operator = (const U &u) { 
        cout << "generic copy assigment\n"; 
    } 
 
    void operator = (const Foo<T> &f) { 
        cout << "specific copy assigment\n"; 
    } 
}; 

输出是“特定的复制赋值”。

换句话说,当类别启用移动时,将选择通用移动而不是特定移动,而如果类别不启用移动,则选择特定副本而不是通用移动。

这是 Visual Studio 2010 的错误还是 c++0x 规范中定义了这种行为?

请您参考如下方法:

您的模板不是“通用移动分配”。但它是一个“完美的转发器”,除了在你的情况下它不转发。 C++0x 中的规则是模板参数推导特别对待参数“T&&”:左值参数将 T 推导为 ArgType&,而右值参数将其推导为 参数类型。这样,ArgType 类型的左值将屈服于最终参数类型 ArgType&,而右值最终将屈服于 ArgType&&

在您的例子中,右手边的左值产生一个推导的参数类型“Foo &”,它与左值参数完全匹配。

不过,目前的草案 (n3126) 禁止编译器使用模板来执行复制赋值(在一个措辞非常困惑的段落中)。取决于issue 1080的分辨率这是否会改变。


标签:C++
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号