10

这个故事与我之前的问题类似。所有支持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;
}

住在godbolt.com


这段代码使用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;
}

住在godbolt.com


显然它不是很方便,特别是当你有很多这样的类,并导致样板代码。基本上,继承构造函数旨在解决的问题。在这种情况下,GCC 的这种行为使这个很棒的c++11功能不可用。

所以我真的很好奇我是否在做违反标准的事情,或者这是 GCC 中的错误?


编辑:

提交了错误报告

4

2 回答 2

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;
};

它看起来确实像一个错误。

于 2017-05-19T06:21:47.510 回答
2

我可能是错的,但引用[class.this]中的 n4527 草案标准:

在非静态 (9.3) 成员函数的主体中,关键字 this 是一个纯右值表达式,其值是调用该函数的对象的地址。类 X 的成员函数中 this 的类型是 X*。

在 OP 的代码中, 的初始化SomeFooWrapper::foo没有发生在成员函数中。因此,就标准而言,关键字this没有合理的含义。

还是我错过了什么?

于 2017-05-19T07:17:24.603 回答