On Wed, 12 Jun 2024 at 10:40, Frederick Virchanza Gotham via Std-Proposals <std-proposals@lists.isocpp.org> 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?