【问题标题】:Can copy/move constructors be inherited by using-declaration in c++17?复制/移动构造函数可以通过 c++17 中的 using-declaration 继承吗?
【发布时间】:2020-05-05 14:23:19
【问题描述】:
struct B {
B(int) {}
B(B const&) {}
};
struct D: B {
using B::B;
};
int main(void) {
B b(5);
D d(b); // error
return 0;
}
c++14 在 12.9 [class.inhctor]/p3 中从继承的构造函数中明确排除了复制/移动构造函数。
对于继承的候选集中的每个非模板构造函数
除了没有参数的构造函数之外的构造函数或
具有单个参数的复制/移动构造函数,构造函数是
隐式声明具有相同的构造函数特征,除非
有一个用户声明的具有相同签名的构造函数
出现 using 声明或构造函数的完整类
将是该类的默认、复制或移动构造函数。
但是我在 c++17 中找不到任何详细的描述。 clang/gcc 表明基类的复制/移动构造函数不是继承的。有人可以提供标准中解释的地方吗?谢谢。
【问题讨论】:
标签:
c++
c++14
c++17
language-lawyer
inherited-constructors
【解决方案1】:
新的措辞在[over.match.funcs]/8:
从类类型 C ([class.inhctor.init]) 继承的构造函数,其第一个参数类型为“引用 cv1 P”(包括从如果参数列表只有一个参数并且C 与P 和@ 引用相关,则在构造cv2 D 类型的对象时,从候选函数集中排除987654327@ 与 D 引用相关。 [例子:
struct A {
A(); // #1
A(A &&); // #2
template<typename T> A(T &&); // #3
};
struct B : A {
using A::A;
B(const B &); // #4
B(B &&) = default; // #5, implicitly deleted
struct X { X(X &&) = delete; } x;
};
extern B b1;
B b2 = static_cast<B&&>(b1); // calls #4: #1 is not viable, #2, #3, and #5 are not candidates
struct C { operator B&&(); };
B b3 = C(); // calls #4
— 结束示例 ]
在您的示例中,B 的继承复制构造函数被排除在候选集合之外(该构造函数的第一个参数类型引用 const B,参数列表只有一个参数 - b,并且B 和 D 与引用相关)。
【解决方案2】:
您引用的段落实际上并没有阻止 C++14 中复制构造函数的继承。请考虑一下:
B(B const&, int = 42) {}
这是一个复制构造函数,但它有两个参数。该段落仅排除了具有单个参数的复制构造函数。当你提供这两个参数时,你实际上可以用这个构造函数初始化一个D 对象。
g++ 错误消息提供了一些见解。
note: an inherited constructor is not a candidate for initialization from an expression of the same or derived type
啊哈!在标准草案中快速搜索发现this
从类类型 C (class.inhctor.init) 继承的构造函数具有“对 cv1 P 的引用”类型的第一个参数(包括从模板实例化的此类构造函数)从集合中排除在构造 cv2 D 类型的对象时,如果参数列表只有一个参数并且 C 与 P 和 P 与 D 引用相关。