This story is similar to my previous question. All versions of GCC that support C++11, have this exact behaviour. I could not find any other compiler that struggles with my test case.
The test case:
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;
}
Live on godbolt.com
This piece of code compiles with clang (3.4 through 4.0), icc (16, 17), Visual C++ (19.00.23506).
If I replace constructor inheritance with a hand-written version, then GCC starts to compile the code:
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;
}
Live on godbolt.com
Obviously it is not very handy, especially when you have many such classes, and leads to boilerplate code. Basically, the very thing that inheriting constructors are designed to fix. This behaviour of GCC renders this great c++11 feature unavailable in such cases.
So I am really curious whether I am doing something illegal with regard to the standard or this is a bug in GCC?
Edit:
Filed a bug report.
The problem is not the constructor inheritance, but this line:
Foo foo{*this};
GCC appears to think it will need a default constructor for struct Foo as well, and since the class has a reference, it is not able to do so.
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&)
By adding the default constructor it appears to think it needs, then the code compiles:
struct Foo
{
Foo():foo(*new BaseFooWrapper(0))
{
}
Foo(BaseFooWrapper & foo): foo(foo)
{
}
BaseFooWrapper & foo;
};
It does look like a bug.
I could be wrong, but quoting from the n4527 draft standard in [class.this]:
In the body of a non-static (9.3) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called. The type of this in a member function of a class X is X*.
In the OP's code, the initialisation of SomeFooWrapper::foo
is not taking place in a member function. Therefore the keyword this
has no reasonable meaning as far as the standard is concerned.
Or have I missed something?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With