C++ Logo

std-discussion

Advanced search

Re: Is an implementation required to define an unneeded, implicitly declared as defaulted, virtual destructor?

From: Brian Bi <bbi5291_at_[hidden]>
Date: Sat, 2 Nov 2019 16:29:23 -0400
In the case of default_delete it must be diagnosed. See
http://eel.is/c++draft/unique.ptr.dltr.dflt#4

On Sat, Nov 2, 2019 at 10:40 AM Myria via Std-Discussion <
std-discussion_at_[hidden]> wrote:

> delete for an incomplete type is legal, though it probably should not be.
> If the completed type ends up having a nontrivial destructor, the behavior
> is undefined.
>
> On Sat, Nov 2, 2019 at 07:15 Mark Stegeman via Std-Discussion <
> std-discussion_at_[hidden]> wrote:
>
>> Hi list,
>>
>> I'm having some trouble determining the validity of the following C++17
>> code:
>>
>> ----
>> #include <memory>
>>
>> struct Base {
>> virtual ~Base() = default;
>> };
>>
>> struct Bar;
>> struct Foo : Base {
>> std::unique_ptr<Bar> bar_{};
>> };
>> ----
>>
>> The following standard quotes lead me to believe that this is ill-formed:
>>
>> [class.dtor]/4
>> If a class has no user-declared destructor, a destructor is implicitly
>> declared as defaulted. [...]
>>
>> [class.dtor]/10
>> [...] If a class has a base class with a virtual destructor, its
>> destructor (whether user- or implicitly-declared) is virtual.
>>
>> [class.dtor]/7
>> A destructor that is defaulted and not defined as deleted is implicitly
>> defined when it is odr-used or when it is explicitly defaulted after its
>> first declaration.
>>
>> [class.dtor]/5
>> A defaulted destructor for a class X is defined as deleted if:
>> - X is a union-like class that has a variant member with a non-trivial
>> destructor,
>> - any potentially constructed subobject has class type M (or array
>> thereof) and M has a deleted destructor or a destructor that is
>> inaccessible from the defaulted destructor,
>> - or, for a virtual destructor, lookup of the non-array deallocation
>> function results in an ambiguity or in a function that is deleted or
>> inaccessible from the defaulted destructor.
>>
>> [basic.def.odr]/3
>> [...] A virtual member function is odr-used if it is not pure. [...]
>>
>> I would interpret these quotes as: ~Foo() must be implicitly defined,
>> because it is virtual, defaulted, and not defined as deleted. This ~Foo()
>> must invoke ~std::unique_ptr<Bar>(), which invokes
>> std::default_delete<Bar>, which makes the program ill-formed, because Bar
>> is incomplete.
>>
>> However, practically speaking, since no Foo's are created, there should
>> be no reason to define ~Foo() here. The description of CWG2068 indeed
>> suggests that the intended interpretation is that implementations are not
>> required to define ~Foo() in this example. And the implementations I
>> checked (MSVC, gcc, clang) all accept it as well. So it looks like my
>> interpretation is wrong, but I haven't been able to find why.
>>
>> Could you tell me where my interpretation goes wrong? What have I missed?
>>
>> Thanks
>>
>> See https://stackoverflow.com/q/58543232 for a previous discussion
>>
>> --
>> Std-Discussion mailing list
>> Std-Discussion_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>
> --
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>


-- 
*Brian Bi*

Received on 2019-11-02 15:31:52