这个故事与我之前的question类似。支持 C ++ 11 的所有GCC版本都具有这种确切的行为。我找不到任何其他编译器与我的测试用例挣扎。
测试用例:
struct BaseFooWrapper
{
BaseFooWrapper(int qux)
{ }
};
struct Foo
{
Foo(BaseFooWrapper & foo)
: foo(foo)
{ }
BaseFooWrapper & foo;
};
struct SomeFooWrapper : public BaseFooWrapper
{
using BaseFooWrapper::BaseFooWrapper;
Foo foo{*this};
};
int main()
{
SomeFooWrapper wrapped_foo(1);
return 0;
}
这段代码用 clang (3.4到4.0), icc (16,17), Visual C ++ (19.00.23506)编译)。
如果我用手写版本替换构造函数继承,那么GCC开始编译代码:
struct BaseFooWrapper
{
BaseFooWrapper(int qux)
{ }
};
struct Foo
{
Foo(BaseFooWrapper & foo)
: foo(foo)
{ }
BaseFooWrapper & foo;
};
struct SomeFooWrapper : public BaseFooWrapper
{
SomeFooWrapper(int qux)
: BaseFooWrapper(qux)
{ }
Foo foo{*this};
};
int main()
{
SomeFooWrapper wrapped_foo(1);
return 0;
}
显然它不是很方便,特别是当你有很多这样的类,并导致样板代码。基本上,继承构造函数的目的是设计用于修复。在这种情况下,GCC的这种行为使得这个伟大的 c ++ 11 功能不可用。
所以我真的很好奇我是否正在做一些违法的标准,或者这是GCC中的一个错误?
修改
提交bug report。
答案 0 :(得分:6)
问题不是构造函数继承,而是这一行:
Foo foo{*this};
GCC似乎认为它还需要一个struct Foo的默认构造函数,并且因为该类有一个引用,所以它无法这样做。
error: no matching function for call to 'Foo::Foo()'
<source>:14:5: note: candidate: Foo::Foo(BaseFooWrapper&)
Foo(BaseFooWrapper & foo): foo(foo)
^~~
<source>:14:5: note: candidate expects 1 argument, 0 provided
<source>:10:7: note: candidate: constexpr Foo::Foo(const Foo&)
通过添加默认构造函数,它似乎认为它需要,然后代码编译:
struct Foo
{
Foo():foo(*new BaseFooWrapper(0))
{
}
Foo(BaseFooWrapper & foo): foo(foo)
{
}
BaseFooWrapper & foo;
};
看起来确实像个错误。
答案 1 :(得分:2)
我可能错了,但引用了 [class.this] 中的n4527草案标准:
在非静态(9.3)成员函数的主体中,关键字this是一个值为prvalue的表达式 是调用该函数的对象的地址。这个类型在一个成员函数中 X类是X *。
在OP的代码中,SomeFooWrapper::foo
的初始化不在成员函数中进行。因此,就标准而言,关键字this
没有合理的含义。
或者我错过了什么?