Exploring "= delete" a bit further, I see it's usable with free functions, not just member functions.  Hence this method of checking for dead code, taking into account overload sets, is usable in more contexts than I initially considered.

Thanks again,
Paul

On Tue, Nov 8, 2022 at 10:39 PM Paul Fee <paul.f.fee@gmail.com> wrote:
On Tue, Nov 8, 2022 at 12:47 AM Arthur O'Dwyer <arthur.j.odwyer@gmail.com> wrote:
On Mon, Nov 7, 2022 at 5:57 PM Paul Fee <paul.f.fee@gmail.com> wrote:
Thanks to all for your replies.
My only need for this is during refactoring.  You've collectively given me enough options to address my issue without additions to C++, so we needn't go further.
[...]
My suggestion derived from my current use of "final".  I often place it on a class (despite core-guidelines C.139) to prove that there are no derived classes.  I'm then free to remove redundant use of virtual, which may for example allow the virtual destructor to evaporate, allowing application of the rule-of-zero.

Yes, absolutely. IMO, rule C.139 doesn't have much rationale behind it. In large codebases (like, industry-size, not hobby-project-size), I think it's quite useful to mark leaf classes as `final` (this helps ensure your coworkers never introduce "grandchild classes" without really thinking about it) and even to mark some non-OOP classes as `final` if they're named or used in ways that make them easily confusable with OOP classes (here `final` means "Don't worry, this isn't a base class").

Another refactor is to mark copy constructors "= delete", to prove they're never used.  This allows a redundant user-declared implementation to be removed without fear of impacting behaviour.

Yep. Speaking of refactoring and overload sets, I've found `=delete` quite useful for ordinary (if bad-coding-style'd) overload sets too. Suppose we have

   void subscribe(Actor*, int, bool = false);  // #1
   void subscribe(Actor*, bool = false);  // #2

We suspect that overload #1 is unused. We comment it out, and the codebase still compiles, so we think it's safe to remove. But by removing it we introduced a bug! Somewhere further down in the codebase, we have a call-site like this:
    subscribe(p, 42);
This used to call #1 as the best match; but with #1 eliminated, it will happily call #2 instead.
The "right" way to test whether #1 is unused is not to comment it out, but to mark it `=delete`. This makes all its callers ill-formed without changing the overload resolution, so we can be sure we're seeing all the call-sites (where we hope that the set of all call-sites is empty).

HTH,
Arthur

Thanks, that's a great tip.  I'll be using "= delete" even more now whilst refactoring.