Следующий код компилируется и связывается с Visual Studio
(как 2017, так и 2019 с /permissive-
), но не компилируется с gcc
или clang
.
foo.h
#include <memory>
struct Base {
virtual ~Base() = default; // (1)
};
struct Foo : public Base {
Foo(); // (2)
struct Bar;
std::unique_ptr<Bar> bar_;
};
foo.cpp
#include "foo.h"
struct Foo::Bar {}; // (3)
Foo::Foo() = default;
main.cpp
#include "foo.h"
int main() {
auto foo = std::make_unique<Foo>();
}
Насколько я понимаю, в main.cpp
, Foo::Bar
необходимобыть полным типом, потому что попытка его удаления выполняется в ~Foo()
, который неявно объявляется и, следовательно, неявно определяется в каждой единице перевода, которая обращается к нему.
Однако Visual Studio
не соглашается и принимает этот код,Кроме того, я обнаружил, что следующие изменения заставляют Visual Studio
отклонять код:
- Делает
(1)
не виртуальным - Определение
(2)
встроенным - то есть Foo() = default;
или Foo(){};
- Удаление
(3)
Мне кажется, что Visual Studio
не определяет неявный деструктор везде, где он используется при следующих условиях:
- Неявный деструктор является виртуальным
- В классе есть конструктор, который определен в другой единице перевода
Вместо этого, кажется, он определяет деструктор только вмодуль перевода, который также содержит определение конструктора во втором условии.
Так что теперь мне интересно:
- Это разрешено?
- Указано ли где-либо или, по крайней мере, известно, что
Visual Studio
это делает?
Обновление: Я отправил отчет об ошибке https://developercommunity.visualstudio.com/content/problem/790224/implictly-declared-virtual-destructor-does-not-app.html. Давайте посмотрим, что из этого делают эксперты.