Все версии GCC борются с инициализатором членов по умолчанию, который захватывает это, в сочетании с унаследованными конструкторами

Эта история похожа на мою предыдущую вопрос. Все версии GCC, которые поддерживают C ++ 11, есть такое точное поведение. Я не смог найти другой компилятор, который борется с моим тестовым примером.

Контрольный пример:

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


Этот кусок кода компилируется с лязг (От 3,4 до 4,0), МЦХ (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?


Редактировать:

Подал сообщение об ошибке.

10

Решение

Проблема не в наследовании конструктора, а в следующей строке:

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

Это похоже на ошибку.

6

Другие решения

Я могу ошибаться, но цитирую проект стандарта n4527 в [class.this]:

В теле нестатической (9.3) функции-члена ключевое слово this является выражением prvalue, значение которого
адрес объекта, для которого вызывается функция. Тип этого в функции-члене
класс X — это X *.

В коде ОП инициализация SomeFooWrapper::foo не происходит в функции члена. Поэтому ключевое слово this не имеет разумного значения в отношении стандарта.

Или я что-то пропустил?

2

По вопросам рекламы [email protected]