所有版本的GCC都与默认成员初始化器相媲美,它捕获了这个,并与继承的构造函数相结合

时间:2017-05-19 05:50:01

标签: c++ c++11 gcc inheriting-constructors

这个故事与我之前的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;
}

住在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中的一个错误?

修改

提交bug report

2 个答案:

答案 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没有合理的含义。

或者我错过了什么?