C++ Logo

std-proposals

Advanced search

Re: Conditional final class-virt-specifier

From: Paweł Benetkiewicz <pawel.benetkiewicz_at_[hidden]>
Date: Tue, 14 Jul 2020 10:56:04 +0200
Thank you very much for your responses. Here are mine responses for your
questions and a few comments:

> I also think this idea is dysfunctional. […] That's kind of a big change
in how `final` works.
Modern C++ compilers use LARL as resolving ambiguity may (and often do)
require a separate pass. Or many passes. In fact, C++ can require an
infinite lookahead.
Unconditional final remains the same, conditional final may require
additional pass, same as any other `constraint-logical-or-expression`.
I could call it a big change before introducing
`constraint-logical-or-expression` in C++20. But once we have concepts, I
don't see the need for any change.
I am surprised about feedback as it seems you wrote about resolving
condition at first pass and forgot `constraint-logical-or-expression` can
require multiple passes or forgot I've proposed condition to be
`constraint-logical-or-expression` and not `constant-expression`.

> On a similar note, how is your `is_final` supposed to function at all?
1) unary is_final (is_final<class T>) should be true if the function is
unconditionally final (single one word final specifier as before proposal).
In other words: true if no class can derive from T.
2) relation is_final (is_final< class Base, class Derived>) should be true
if Derived derives from Base and either Base is unconditionally final or
it's conditionally final and `constraint-logical-or-expression` of
`final-clause` is true (optionally with Derived temporary used as
`identifier` in `final-head`). In other words: true if Derived can derive
from Base.

It could be also split into two separate type traits like
is_unconditionally_final and is_conditionally_final, but it could break
backwards compatibility.

> I have never *heard *of "conditional inheritance."
Just first few googled examples:
-
https://stackoverflow.com/questions/5040831/restrict-the-classes-that-may-implement-an-interface
<https://stackoverflow.com/questions/40967838/how-to-restrict-the-interface-implementation-in-c-sharp>
<https://softwareengineering.stackexchange.com/questions/316206/how-to-make-interfaces-usable-for-special-classes-only>
-
https://stackoverflow.com/questions/5767160/allowing-implementing-interface-only-for-specific-classes
-
https://stackoverflow.com/questions/26465237/allow-a-mock-class-to-inherit-from-a-final-class
-
https://stackoverflow.com/questions/33007574/restrict-classes-that-can-implement-interface-in-java
-
https://stackoverflow.com/questions/40094218/can-i-limit-which-classes-can-implement-an-interface
-
https://stackoverflow.com/questions/40967838/how-to-restrict-the-interface-implementation-in-c-sharp
-
https://softwareengineering.stackexchange.com/questions/316206/how-to-make-interfaces-usable-for-special-classes-only
There are many requests for a conditional inheritance across many languages.
Some languages already supports limited functionality to my proposal,
restricting inheritance:
- PostSharp has `InternalImplement` attribute, see "Restricting Interface
Implementation": https://doc.postsharp.net/control-implementation
- Kotlin allows inheriting from sealed in same file:
https://kotlinlang.org/docs/reference/sealed-classes.html
This pybind commit is a great example of why my proposal is useful:
https://github.com/pybind/pybind11/pull/2151/files

> At this point, the name `E` is undeclared, so this can't possibly work.
It does not need to be declared, as it's a `constraint-logical-or-expression`.
It needs to be declared for final conditioning only,
Look for this example (not proposal related, but also uses `
constraint-logical-or-expression`):
```
template<class T>
  requires std::is_same_v<T, C>
void f();
struct C {};
```
Here, C in the second line of code also is not defined (not ever declared)
but it's ok, as it's found on the second pass.
The Same rules apply for my proposal, as it's also
`constraint-logical-or-expression`
and not `constant-expression`.

> Not okay; redefinition of struct `F`.
Indeed my bad in R0 as there is no partial classes support in raw ISO C++:
- struct F : D {}; // OK: F derives from E
- struct G : D {}; // ill-formed: G does not derive from E
+ struct H : F, D {}; // OK: F derives from E
+ struct I : G, D {}; // ill-formed: G does not derive from E
Also, there should be 'In case (3)', not 'In case (2)' in the Example
section of proposal, and note in Wording/8 should be marked as added
(green).

> Furthermore: the proposal states "Disadvantages: none", "Design trade-offs:
none". While the latter may end up being somewhat accurate, the first one
is complete nonsense, rendering this proposal technically ill-formed.
So will it be ok if I change 'Disadvantages' from "None" to "Proposal
increases complexity of language by adding optional `final-clause`."?
I've read a few proposals (both PR… and N…) and I didn't find such
sentences.

> So the basic question "why is this worth having?" is not answered by the
proposal.
The Proposal is worth having, because it does "heavily increase
compatibility correctness by inheritance constraints" by providing an
ability to encapsulate interfaces. [Note: See Examples section of proposal.
— end note]

Best regards.

Received on 2020-07-14 03:59:33