On Tue, Nov 8, 2022 at 3:24 AM Paul Fee via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
Hello,

The "final" and "override" specifiers can be useful to ensure code using inheritance is implemented as expected.  However there are some gaps where I find some features lacking, I can't express some approaches nor get the compiler to confirm my assumptions.  When refactoring large codebases, one may wish to make an isolated API change but inadvertently changes code that's part of a class hierarchy.  Some additional specifiers may allow developers to proceed with caution, protecting them before breaking functionality.

Example:

struct Base
{
  virtual bool state() { return false; }
};

struct Derived : public Base
{
  bool state() { return s; }
private:
  bool s = false;
}

One may opt to refactor state() to make it a const method, without noticing there's also an implementation in the base class as "virtual" is only necessary in the base class.  Such a change should be applied consistently throughout the hierarchy.  I'd like the compiler to confirm that the member function does NOT override a base class function, then I'd be able to follow up with broader refactoring knowing the impact of the change is limited to just one class.  The final specifier means I don't need to look further down the class hierarchy, but I don't have a specifier that ensures I don't need to look up the hierarchy.

Step 1: If this still compiles, then we know there'll be no surprises when changing the API.
struct Derived final : public Base
{
  bool state() !override { return s; }
private:
  bool s = false;
}

Step 2: state function signature can be safely changed.
struct Derived final : public Base
{
  bool state() const !override { return s; }
private:
  bool s = false;
}

Here !override is use as example syntax, but that was just to illustrate the idea.  When refactoring, step 1 would fail to compile because Derived::state() does override Base::state().  This alerts the developer to the danger of only changing the derived class.

Would it be reasonable to enhance the set of specifiers so that more scenarios can be expressed, allowing the compiler to confirm if the developer's assumptions are correct?  For example:

* function must/must not override a base class function
* function must/must not be part of a group of overloads
* function must/must not be virtual

It doesn't work.  You'd need to update all the code in the universe to mark every function that doesn't override `!override` in order for the diagnostic to be generated.