C++17 中复制构造函数的继承
Inheritance of copy constructors in C++17
请考虑以下示例:
struct Parent
{
Parent ();
Parent (const Parent &);
};
struct Child : public Parent
{
using Parent::Parent;
};
Parent p;
Child c (p);
这取自以下问题:为什么"继承的构造函数不是从相同或派生类型的表达式初始化的候选者"?
最初的问题是关于C++11的。在 C++11 中,有一些措辞阻止Child
获取需要const Parent&
的构造函数:
候选集合中的每个非模板构造函数,除了没有参数的构造函数或具有单个参数的复制/移动构造函数之外,构造函数将隐式声明具有相同的构造函数特征,除非存在具有相同构造函数的用户声明构造函数 出现using 声明的类中的签名。
N4429 显着更改了继承构造函数的规范,并被认为追溯到 C++11(我认为?N4429 的目的是使基类构造函数可见,就好像它们是派生类构造函数一样,而不是声明委托给基类构造函数的派生类构造函数。在 N4429 的第一个版本中,有以下措辞,将限制从 C++11 开始:
当 using-声明声明类从基类继承构造函数时,基类的默认构造函数、复制构造函数和移动构造函数(如果有(将从引入的声明集中排除。
然而,P0136R0,在本文的更新版本中,这一措辞已不复存在,也没有解释原因。该论文再次修订,然后合并到标准中。因此,在 C++17 中,我看不到任何会阻止上述代码编译的规则。
尽管如此,GCC和Clang都拒绝了它。叮当 说:
继承的构造函数不是从相同或派生类型的表达式初始化的候选项
但是,我在标准中找不到任何这样的说法。
此代码在 C++17 中格式不正确吗?如果是这样,为什么?
[over.match.funcs]/8:
从类类型
C
([class.inhctor.init]( 继承的构造函数具有类型为"对 cv1P
的引用"的第一个参数(包括从模板实例化的此类构造函数(在构造cv2类型的对象时D
如果参数列表只有一个参数并且C
与P
引用相关,并且P
与D
引用相关。
请参阅CWG2356。
我认为WG21的规则是:
基类复制和移动构造函数引入派生类 在以下情况下,重载解析不考虑使用声明 构造派生类对象。
如果 Base 的继承构造函数之一恰好具有与派生的复制/移动构造函数匹配的签名,则不会阻止派生复制/移动构造函数的隐式生成。
请注意,using A::A;
指令继承所有构造函数,包括复制/移动和编译器生成的A
的默认构造函数,到出现此指令的派生类中;在查找派生类的构造函数或形成候选集时,将考虑 A 的所有构造函数(复制/移动和编译器生成的默认构造函数除外(。
struct B { B(); };
struct D : B { using B::B; };
D d{ B() }; // error: overload resolution found nothing. #1
D d{ D() }; // OK #2
默认的复制构造函数B::B(const B&)
继承到D
但此构造函数不是候选函数。如果没有 using 指令,程序的格式正确,因为这被视为聚合初始化。此外,using-声明不会阻止编译器生成D
的默认复制/移动构造函数,这就是为什么#2是可以的。
现在为了抑制此错误,我们将显式提供一个用户提供的复制构造函数:
struct B{
B();
};
struct D : public B{
using B::B;
B(const B&);
};
D d{ B() }; // OK: overload resolution found constructor matches the argument-list.
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- C++继承:构造函数中的字符串构造
- 继承构造函数和其他变量的解决方法
- 带有此指针的模板类多重继承构造函数不起作用?
- 虚拟继承构造函数的组装
- C++继承构造函数的可见性
- 继承构造函数(ISO 2011 SEC 12.9第7段)
- 没有C 11的继承构造函数
- 使用关键字继承构造函数时出乎意料的行为
- 继承构造函数不允许类似数组的初始化
- 从基于QObject的类继承构造函数
- 继承构造函数并提供新的重载:无参数基构造函数似乎不参与重载解析
- C++多继承构造函数
- 具有独占继承构造函数的类的值初始化
- C++ 继承构造函数重写
- 继承构造函数与转发
- 默认情况下继承构造函数 noexcept(true)
- 有没有办法在继承构造函数时访问初始值设定项列表
- 从 std::function 继承构造函数时"function returning a function"