copy/move构造函数可以通过c++17中的using-declaration继承吗?
Can copy/move constructors be inherited by using-declaration in c++17?
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.
中从继承的构造函数中显式排除 copy/move 构造函数
For each non-template constructor in the candidate set of inherited
constructors other than a constructor having no parameters or a
copy/move constructor having a single parameter, a constructor is
implicitly declared with the same constructor characteristics unless
there is a user-declared constructor with the same signature in the
complete class where the using-declaration appears or the constructor
would be a default, copy, or move constructor for that class.
但是我在c++17中找不到任何详细的描述。 clang/gcc 显示基 class 的 copy/move 构造函数未被继承。有人可以提供标准中解释的地方吗?谢谢
新的措辞在[over.match.funcs]/8:
A constructor inherited from class type C
([class.inhctor.init]) that has a first parameter of type “reference to cv1 P
” (including such a constructor instantiated from a template) is excluded from the set of candidate functions when constructing an object of type cv2 D
if the argument list has exactly one argument and C
is reference-related to P
and P
is reference-related to D
. [ Example:
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
— end example ]
在您的示例中,B
的继承复制构造函数被排除在候选集合之外(该构造函数的第一个参数类型为 const B
,参数列表只有一个参数- b
和 B
和 D
是参考相关的)。
你引用的段落实际上并没有阻止 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
A constructor inherited from class type C (class.inhctor.init) that has a first parameter of type “reference to cv1 P” (including such a constructor instantiated from a template) is excluded from the set of candidate functions when constructing an object of type cv2 D if the argument list has exactly one argument and C is reference-related to P and P is reference-related to D.
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.
中从继承的构造函数中显式排除 copy/move 构造函数For each non-template constructor in the candidate set of inherited constructors other than a constructor having no parameters or a copy/move constructor having a single parameter, a constructor is implicitly declared with the same constructor characteristics unless there is a user-declared constructor with the same signature in the complete class where the using-declaration appears or the constructor would be a default, copy, or move constructor for that class.
但是我在c++17中找不到任何详细的描述。 clang/gcc 显示基 class 的 copy/move 构造函数未被继承。有人可以提供标准中解释的地方吗?谢谢
新的措辞在[over.match.funcs]/8:
A constructor inherited from class type
C
([class.inhctor.init]) that has a first parameter of type “reference to cv1P
” (including such a constructor instantiated from a template) is excluded from the set of candidate functions when constructing an object of type cv2D
if the argument list has exactly one argument andC
is reference-related toP
andP
is reference-related toD
. [ Example: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
— end example ]
在您的示例中,B
的继承复制构造函数被排除在候选集合之外(该构造函数的第一个参数类型为 const B
,参数列表只有一个参数- b
和 B
和 D
是参考相关的)。
你引用的段落实际上并没有阻止 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
A constructor inherited from class type C (class.inhctor.init) that has a first parameter of type “reference to cv1 P” (including such a constructor instantiated from a template) is excluded from the set of candidate functions when constructing an object of type cv2 D if the argument list has exactly one argument and C is reference-related to P and P is reference-related to D.