lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] depr.impldec


From: Vadim Zeitlin
Subject: Re: [lmi] depr.impldec
Date: Sun, 10 Jul 2022 14:29:22 +0200

On Sat, 9 Jul 2022 22:58:19 +0000 Greg Chicares <gchicares@sbcglobal.net> wrote:

GC> clang's '-Wdeprecated-copy-with-dtor' pointed out that we're relying
GC> on a deprecated language feature [depr.impldec] in quite a few instances,
GC> which I'd like to fix now, lest "deprecated" become "deleted".

 I agree with fixing it, but I'd do it in a different way and rather
explicitly write out the defaulted copy ctors (and assignment operators if
necessary) rather than deleting the existing dtors. My rationale for this
is that having the copy ctor in the class declarations makes it immediately
clear if the class is copyable or not, which can be quite non-obvious
otherwise.

 FWIW I would omit the move ctors and assignment operators instead of
deleting them because the situation is much more clear with move-related
special functions than with the copy-related ones: if they're not
explicitly defined, they're not available -- i.e. the compiler never
provides them implicitly, unlike with the copy ones.

GC> Please review this branch:
GC>   https://git.savannah.nongnu.org/cgit/lmi.git/log/?h=odd/rules_of_n

 I don't have any meaningful comments on it, just a couple of nitpicks,
please see my replies to the Git notifications.

GC> Somewhere, Scott Meyers said he disliked the Rule of Zero because he
GC> sometimes experimentally adds a dtor as a convenient debugger breakpoint,
GC> and adding one instead of five special members can break things. I don't
GC> think I've used a debugger successfully in the present century, though.

 I do use it often, but this is just a minor convenience. The loss of
clarity is IMO a much bigger problem with the Rule of Zero and personally I
wouldn't use it except for completely trivial struct-like classes.

GC> I was torn between writing "= default" vs. "= delete".

 Sorry if I'm missing something, but this one seems obvious to me: you
should write "= delete" everywhere you can, i.e. everywhere where it can be
written without breaking the build, and "= default" elsewhere.

GC> I was tempted to remove "virtual" from dtors for classes that don't
GC> manage resources

 Sorry again, but this seems completely contrary to what I would do, is
there a negation missing in the sentence above? Because normally classes
holding resources, such as e.g. std::unique_ptr<>, would _not_ have a
virtual dtor, but other classes, including all those with virtual
functions, would.

GC>  - when writing a non-virtual dtor for a polymorphic class,

 And this seems almost like a contradiction in terms: polymorphic classes
should _always_ have a virtual dtor. In theory it is possible to use a
polymorphic classes without ever deleting it via a pointer to the base
class (which would result in undefined behaviour if the dtor is not
virtual), but in practice it's impossible to ensure this, which is why all
compilers will warn you about not using virtual dtor for a polymorphic
class and, warning aside, it's really a very bad idea to not make the dtor
virtual in such classes.

GC> Those are just my "known unknowns"; I'd be especially interested in
GC> learning about any "unknown unknowns".

 My candidate for the latter is the lack of certainty about whether the
objects of a class are copyable or not.

 FWIW here is my personal strategy for defining the class' special
functions: there are several categories of classes

1. Value-like: for them copy special functions and dtor are explicitly
   defaulted. Move special functions are omitted, and are not available.

2. Container classes: they're almost value-like, but typically require
   defining move functions for efficiency reasons, so they're added,
   and possibly defaulted.

3. Polymorphic classes: for them, copy special functions are explicitly
   deleted and a virtual dtor is defined and possibly defaulted. Move
   special functions are omitted, and are not available as the result.

4. All the rest: for them, copy special functions are explicitly either
   default or deleted and the dtor is explicitly defined as well. Move
   special functions can be explicitly defined if needed.

 This seems relatively complicated, but IMHO is very logical and so not
difficult to remember. It also requires in more typing, but I think it's
worth to define the special copy functions explicitly as they can be a
source of confusion and inefficiencies (e.g. large objects getting copied
when they were not supposed to) otherwise.

 At one time there was hope that metaclasses proposal would allow to make
things both more clear and more concise by allowing to define classes of
different categories above differently, but it doesn't look like this is
ever going to happen any more, unfortunately. So our choice is to either
write the special member functions by hand or to switch to Raku (which does
have metaclasses, of course, because it has everything).

 Regards,
VZ

Attachment: pgpbszmod72FH.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]