Der folgende Code kompiliert und verknüpft mit Visual Studio
(sowohl 2017 als auch 2019 mit /permissive-
), kompiliert jedoch nicht mit entweder gcc
oder 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>(); }
Mein Verständnis ist , dass, in main.cpp
, Foo::Bar
muß eine vollständige Typ sein, weil deren Löschung in versucht wird ~Foo()
, die implizit deklariert und somit implizit in jeder Übersetzungseinheit definiert , die es zugreift.
Ist Visual Studio
jedoch nicht einverstanden und akzeptiert diesen Code. Außerdem habe ich festgestellt, dass die folgenden Änderungen dazu führen, dass Visual Studio
der Code abgelehnt wird:
- Herstellung von
(1)
nicht-virtuellen (2)
Inline definieren - dhFoo() = default;
oderFoo(){};
- Entfernen
(3)
Es sieht für mich so aus Visual Studio
ein impliziter Destruktor nicht überall dort definiert, wo er unter den folgenden Bedingungen verwendet wird:
- Der implizite Destruktor ist virtuell
- Die Klasse verfügt über einen Konstruktor, der in einer anderen Übersetzungseinheit definiert ist
Stattdessen scheint es nur den Destruktor in der Übersetzungseinheit zu definieren, der auch die Definition für den Konstruktor in der zweiten Bedingung enthält.
Jetzt frage ich mich also:
- Ist das erlaubt?
- Ist irgendwo angegeben oder zumindest bekannt, dass dies der
Visual Studio
Fall ist?
Update: Ich habe einen Fehlerbericht https://developercommunity.visualstudio.com/content/problem/790224/implictly-declared-virtual-destructor-does-not-app.html eingereicht . Mal sehen, was die Experten daraus machen.
struct BarDeleter { void operator()(Bar*) const noexcept; };
und ändern Sie den unique_ptr in std::unique_ptr<Bar, BarDeleter> bar_;
. void Foo::BarDeleter::operator()(Foo::Bar* p) const noexcept { try { delete p; } catch(...) {/*discard*/}}