gpt4 book ai didi

templates - 指定了多个复制构造函数

转载 作者:行者123 更新时间:2023-12-01 05:37:21 24 4
gpt4 key购买 nike

使用 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 member function template is NEVER INSTANTIATED to perform the copy of a class object to an object of its class type."



正确的实现应该是:
  • 当 A 或 B 或两者都被删除时,不会发生断言失败。
  • 如果删除 B 行,则 c 的构造应该失败,因为 b 是常量。
  • 如果这两行都被删除,编译器应该为该类生成一个复制构造函数。
  • 如果两条线都存在,则由实现来警告用户。

  • 任何意见?

    最佳答案

    首先,template<T>应该是 template <typename T> .

    我在 64 位 Ubuntu Linux 上使用 gcc 4.4.3,代码的行为与您在帖子中演示的不同。

  • 如果没有任何改变,代码可以在没有任何警告的情况下编译。构造函数 A 和 B 被依次调用。
  • 如果我注释 A 行,则它无法像您所说的那样编译:在行 const MyClass b(a); 中失败.原因是对象a不是常量,所以无法匹配构造函数B,编译器不得不实例化模板构造函数。当然,const MyClassMyClass是不同的类型。
  • 但是,如果我只注释 B 行,则可以成功编译代码并调用模板复制构造函数。对象 b 是一个常量对象,因此构造 A 无法匹配,编译器实例化模板构造函数。然而,问题仍然存在:static_assert 是否应该失败?差异可能是因为平台/编译器的差异。 GCC 似乎实现了 is_same<MyClass&&, MyClass>::value是真实的。您可以使用 typeid 打印出这两种类型。
  • 关于templates - 指定了多个复制构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7884102/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com