The following code compiles and links with Visual Studio (both 2017 and 2019 with /permissive-), but does not compile with either gcc or 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>(); }
My understanding is that, in main.cpp, Foo::Bar must be a complete type, because its deletion is attempted in ~Foo(), which is implicitly declared and therefore implicitly defined in every translation unit that accesses it.
However, Visual Studio does not agree, and accepts this code. Additionally, I've found that the following changes make Visual Studio reject the code:
- Making
(1)non-virtual - Defining
(2)inline -- i.e.Foo() = default;orFoo(){}; - Removing
(3)
It looks to me as if Visual Studio does not define an implicit destructor everywhere it is used under the following conditions:
- The implicit destructor is virtual
- The class has a constructor that is defined in a different translation unit
Instead, it seems to only define the destructor in the translation unit that also contains the definition for the constructor in the second condition.
So now I'm wondering:
- Is this allowed?
- Is it specified anywhere, or at least known, that
Visual Studiodoes this?
Update: I've filed a bug report https://developercommunity.visualstudio.com/content/problem/790224/implictly-declared-virtual-destructor-does-not-app.html. Let's see what the experts make of this.