使用 Visual C++ 2010,我有一个这样的类:
class MyClass{
public:
MyClass(){}
MyClass(MyClass &){/*...*/} //A
MyClass(const MyClass &){/*...*/} //B
template<typename T> MyClass(T &&t){ static_assert(
!std::is_same<typename
std::remove_cv<typename std::remove_reference<T>::type>::type,
MyClass>::value,
"Wrapping over wrapping is not allowed!"); } //C
};
int main(int, char**){
MyClass a;
const MyClass b(a); //assert fail if line A removed
auto c=b; //assert fail if line B removed
}
//If both A and B exists
//Warning C4521: multiple copy constructors specified
//Furthermore, if both A and B removed
//No error or warnings; VC2010 accepts peacefully.
//In debug mode you will find the compiler generated trivial copy constructor
根据 C++ 标准,A 行和 B 行都被认为是复制构造函数,而 C 是转换构造函数。我收到一条警告说我声明了多个复制构造函数,这并不奇怪。但是,如果我删除其中任何一个,static_assert 将失败并且代码将无法编译,这意味着模板构造函数获得了控制权。
我确信这种行为遵循函数重载的规则。然而,这是两个规则的冲突吗?如果 A 和 B 是复制构造函数并且声明了其中一个,那么任何复制对象的尝试都不应该放到模板中,对吗?
更新:根据 N3242, 12.8.7,
“成员函数模板永远不会被实例化来执行将类对象复制到其类类型的对象。”
正确的实现应该是:
- 当 A 或 B 或两者都被移除时,不应发生断言失败。
- 如果删除了行 B,则 c 的构造应该会失败,因为 b 是 const。
- 如果这两行都被删除,编译器应该为该类生成一个复制构造函数。
- 如果两条线都存在,则由实现来警告用户。
任何意见?