MSVC 19 удаляет унаследованные конструкторы - PullRequest
0 голосов
/ 28 февраля 2019

Согласно MSVC 19.16, если класс B явно наследует от класса A конструкторы, а также определяет свои собственные конструкторы, унаследованные конструкторы игнорируются.

class A {
public:
    A() {}
    A(int x) {}
};

class B : public A {
public:
    using A::A;

    B(double x) : A() {}
};

int main()
{
    B b;                 // error C2512: 'B': no appropriate default constructor available
                         // note: see declaration of 'B'
    return 0;
}

Компилируется правильно в gcc.Кто-нибудь знает, это ошибка компилятора или я что-то пропустил?Спасибо.

Ответы [ 3 ]

0 голосов
/ 28 февраля 2019

Полагаю, это ошибка компилятора MSVC 19.16.

Если вы напишите

class B : public A {
    B(double) : A() {}
};

// ...

B b;

, вы должны получить ошибку от каждого компилятора, поскольку конструктор B(double) удаляет значение по умолчанию B()constructor.

Но, согласно этой странице (ищите "Наследование конструкторов")

Если объявление использования ссылается на конструктор прямой базыопределяемый класс (например, с использованием Base :: Base;), все конструкторы этой базы (игнорируя доступ к элементу) становятся видимыми для разрешения перегрузки при инициализации производного класса.

Если разрешение перегрузки выбирает унаследованный конструктор,он доступен, если он будет доступен, когда используется для создания объекта соответствующего базового класса: доступность введенного объявления using игнорируется.

Если при перегрузке разрешение перегрузки выбирает один из унаследованных конструкторов при инициализацииобъект такого производного класса, затем подобъект Base, из которого был унаследован конструкторited инициализируется с использованием унаследованного конструктора, а все остальные базы и члены Derived инициализируются так, как если бы использовался конструктор по умолчанию (по умолчанию используются инициализаторы членов по умолчанию, в противном случае происходит инициализация по умолчанию).Вся инициализация обрабатывается как один вызов функции: инициализация параметров унаследованного конструктора выполняется до инициализации любой базы или члена производного объекта.

Таким образом, в этом случае объявление using A::A; должно преобразовать конструкторы A в конструкторы B.

Другой пример.

Определение B только с конструктором, который получает std::string,

class B : public A {
public:
    using A::A;

    B(std::string) : A() {}
};

должна быть возможна инициализация B с целым числом

B  b(1);

, потому что конструктор A(int) наследуется какB конструктор.

0 голосов
/ 01 марта 2019

Возможно, не ошибка.

C ++ 14 [class.inhctor] ¶3

Для каждого не шаблонного конструктора в наборе кандидатов унаследованных конструкторов кроме конструктора без параметров или конструктора копирования / перемещения с одним параметром, конструктор неявно объявляется с такими же характеристиками конструктора ...

Так до C ++ 17,конструкторы по умолчанию не были наследуемыми, а ваш пример был некорректным.

Это изменилось, когда P0136 удалил весь раздел [class.inhctor] и поместил формулировку для наследования конструкторов в [пространство имен.вместо].За это проголосовали за C ++ 17, но поскольку это было частью устранения дефекта, реализациям также разрешается применять его задним числом к ​​предыдущим версиям стандарта.

Так что ваш пример действителен C ++ 17и потенциально допустимые C ++ 11 и C ++ 14 в зависимости от того, решил ли ваш поставщик компиляторов применить это изменение задним числом при компиляции в соответствии с этими версиями стандарта.Соответствующие компиляторы должны принять этот пример при компиляции в режиме C ++ 17 и в пределах своих прав принять или отклонить этот пример при компиляции в режиме C ++ 11 или C ++ 14, в зависимости от решений своих поставщиков.

CWG2273 также может быть связано.

Обратите внимание, что в вашем примере MSVC 19.16 игнорирует только A::A().Это не игнорирование A::A(int x).

0 голосов
/ 28 февраля 2019

Если мы укажем /std:c++14, он все равно скомпилируется с ошибкой.Но /std:c++17 или /std:c++latest заставляют его компилироваться.Так что похоже на ошибку в MSVC.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...