C++ Logo

std-proposals

Advanced search

[std-proposals] !override

From: Paul Fee <paul.f.fee_at_[hidden]>
Date: Mon, 7 Nov 2022 16:23:58 +0000
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

Thanks,
Paul

Received on 2022-11-07 16:24:09