C++ Logo

std-proposals

Advanced search

Re: [std-proposals] explicit class (2023, 2019, 2004, 2002)

From: Jonathan Wakely <cxx_at_[hidden]>
Date: Wed, 12 Jun 2024 13:55:20 +0100
On Wed, 12 Jun 2024 at 10:40, Frederick Virchanza Gotham via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On Tue, Jun 11, 2024 at 3:30 PM Jonathan Wakely wrote:
> >
> > Why should a language feature be introduced for a
> > personal preference? Write a clang-tidy check.
>
>
> You can throw that argument at a lot of good language features. A few
> examples:
>
> - Instead of marking a constructor as explicit, use a 3rd party code
> analysis tool to detect the use of an implicit conversion that uses a
> constructor.
>

Clang-tidy didn't exist in the mid '90s. But having all constructors be
explicit would actually be useful, unlike your other suggestions. But you
can already write that explicitly, so I don't see why we need 'explicit
class' to do that.

Also, explicit applies to more than just constructors, why would you
restrict it to constructors and not conversion operators?



> - Instead of deleting the move constructor, use a 3rd party code
> analysis tool to detect the passing of an Rvalue of type
> "decltype(*this)" to a constructor.
>

You should never delete a move constructor. Why would you even want that?


> - Instead of marking a virtual function as " = 0 " in the base class,
> use a 3rd party code analysis tool to ensure that an object of the
> base class is never created by itself, and that any derived classes
> override the base class's virtual function.
>

There's a semantic difference between "users of this interface can never
create the abstract class" and "none of the code I am able to scan creates
an instance of the base class".

An analyzer can only scan the code you have access to. For your proposal,
why would you care if user code consuming your headers prefixes all member
accesses with this-> ? Why should your preference be imposed on their code?
What semantic difference does it make? What new abilities does that feature
give to the language, and why should it be enforced on all code using your
header, rather than just on your own code?


> - Instead of marking a variable as 'const', write a comment " // never
> changes" after the variable declaration, and use a 3rd party code
> analysis tool to detect the changing of the value of a variable that
> was declared with " // never changes" after it.
>

Writing "this->" before a member access doesn't prevent misuse, or allow
you to reason about the code differently, except in the most superficial
way.

Your suggestions don't enable anything new in the language, they just tweak
some defaults, to create a new dialect. Abstract classes and const are not
in the same category. They allow different APIs to be expressed. An API
that takes a const char* is different to one that takes char*. That's not
the case for your proposals, which would just enforce stylistic choices.


> I can go on and on.
>
> In my original post, I listed 5 effects of "explicit class":
> - All miranda functions deleted by default
>

You can do this today by defining them as = delete


> - Any constructor is 'explicit' by default
>

You can do this today with explicit on constructors (and conversion
operators).


> - Overridden functions must be marked 'virtual override'
>

Conflicts with convention.


> - Must confirm to compiler that you realise you're overriding a
> non-virtual with a virtual
>

You can do this today with -Werror=overloaded-virtual and then a
using-declaration to unhide the base's non-virtual function, which confirms
you realise you're doing it.


> - Must write "this->" before every member
>

You can do this manually today, and if you forget ... nothing bad happens.
So what's the point anyway?


>
> Maybe I'm going a bit far with it now, but maybe we could opt
> individually into the restrictions:
>
> class MyClass
>
> restrict[no_mirandas,explicit_default,must_mark_override,nonv-mark-override,must_this]
>

Good grief.


> {
> };
>
> Of the five effects I listed above, the two I'm most interested in are:
> - All miranda functions deleted by default
>

What's the advantage of deleting the destructor? How often do you need that?

If the aim is "explicitness", to be clear about what you want the class to
do, why not just explicitly define them as deleted? Why do you want to make
it easier to be explicit, that defeats the purpose of being explicit.



> - Must write "this->" before every member
>
> Maybe other people are more interested in the other three?
>
> Also another new restriction I would like is demonstrated in the
> following program:
>
> struct monkey {};
>
> int monkey;
>
> int main(void)
> {
> monkey = 5;
> }
>
> It was a really really really bad idea back in the 1970's to allow C
> to give a struct the same name as a variable.


Why? In C you can't refer to the struct without saying 'struct monkey'
which disambiguates it. Only C++ lets you use it without the struct (or
class) keyword.


> I would like to see this
> deprecated in C++26, and made a compiler error in either C++29 to
> C++32.
>

Why?

Received on 2024-06-12 12:56:42