Date: Sat, 11 Jul 2020 11:53:08 -0400
Broadly speaking, if you're going to post a PDF link, it would be a
good idea to at least put the abstract of what the idea is in the text
of the post. That way, we don't have to read an attachment just to get
an idea of what is being suggested.
>From an editorial perspective, the "motivation" section does not
appear to actually describe the motivation for the feature. It
describes what the feature is and how it relates to other features.
But it doesn't say why it should exist.
Something more like an actual motivation appears in the "examples"
section, since they explain where you would use them and why. But even
these are kind of thin in terms of why they are important enough to
warrant a language change.
I also think this idea is dysfunctional. Consider one of your examples:
```
class extension final<class B>(B::api_version < extension::api_version)
```
OK, so the compiler is going to be compiling the following code, and
it needs to determine if it is valid:
```
class Derived : extension // #1
{
public:
constexpr int api_version = something; //#2
};
```
The humorous part here is that, if line #2 doesn't exist,
`Derived::api_version` always equals `extension::api_version` because
they are *the same thing*. `Derived` inherited it from `extenion`,
after all. So all you're really testing is whether the user overrode
the version, which I don't think is a particularly useful check. But
that's not the real problem.
The real problem is that the validity of line #1 is based on the
contents of line #2. But that's not how `final` works; the `final`
check happens in line #1. To do what you want requires the compiler to
defer the check until the end of `Derived`'s definition.
That's kind of a big change in how `final` works. When you
characterize this as basically just like `explicit(bool)`, I don't see
the similarity. `explicit(bool)` works in exactly the same way as
regular old `explicit`. It doesn't require deferring the check of
whether a function is `explicit` to some later point in the code. The
feature you've suggested requires a fundamentally different
implementation (and probably standard specification) from regular
`final`.
On a similar note, how is your `is_final` supposed to function at all?
I question the usefulness of `is_final` in general, but presumably the
point is to use it to guard code of the form `class SomeType : Base`
and avoid a compile error if that can't be done. Well, if you're going
to ask `is_final<SomeType, Base>`, then `SomeType` *cannot* be a
complete class yet. Otherwise you'd have already done the inheritance
and you'd already have a compile error.
And if `SomeType` isn't complete, how can you determine whether you
can inherit from `Base` if `Base`'s conditions *require* access to
`SomeType`'s full definition?
Overall, I don't think your proposal works if you require the
expression to be able to use the derived class as though it were a
complete class. And if you take that out... how useful is this
functionality? After all, 2 out of 3 of your examples require the
derived class to be complete. If you take those away, all you're left
with is preventing a class from being the base class of anything but
some specific set of classes.
And is that *really* important enough to ask for a whole language feature?
good idea to at least put the abstract of what the idea is in the text
of the post. That way, we don't have to read an attachment just to get
an idea of what is being suggested.
>From an editorial perspective, the "motivation" section does not
appear to actually describe the motivation for the feature. It
describes what the feature is and how it relates to other features.
But it doesn't say why it should exist.
Something more like an actual motivation appears in the "examples"
section, since they explain where you would use them and why. But even
these are kind of thin in terms of why they are important enough to
warrant a language change.
I also think this idea is dysfunctional. Consider one of your examples:
```
class extension final<class B>(B::api_version < extension::api_version)
```
OK, so the compiler is going to be compiling the following code, and
it needs to determine if it is valid:
```
class Derived : extension // #1
{
public:
constexpr int api_version = something; //#2
};
```
The humorous part here is that, if line #2 doesn't exist,
`Derived::api_version` always equals `extension::api_version` because
they are *the same thing*. `Derived` inherited it from `extenion`,
after all. So all you're really testing is whether the user overrode
the version, which I don't think is a particularly useful check. But
that's not the real problem.
The real problem is that the validity of line #1 is based on the
contents of line #2. But that's not how `final` works; the `final`
check happens in line #1. To do what you want requires the compiler to
defer the check until the end of `Derived`'s definition.
That's kind of a big change in how `final` works. When you
characterize this as basically just like `explicit(bool)`, I don't see
the similarity. `explicit(bool)` works in exactly the same way as
regular old `explicit`. It doesn't require deferring the check of
whether a function is `explicit` to some later point in the code. The
feature you've suggested requires a fundamentally different
implementation (and probably standard specification) from regular
`final`.
On a similar note, how is your `is_final` supposed to function at all?
I question the usefulness of `is_final` in general, but presumably the
point is to use it to guard code of the form `class SomeType : Base`
and avoid a compile error if that can't be done. Well, if you're going
to ask `is_final<SomeType, Base>`, then `SomeType` *cannot* be a
complete class yet. Otherwise you'd have already done the inheritance
and you'd already have a compile error.
And if `SomeType` isn't complete, how can you determine whether you
can inherit from `Base` if `Base`'s conditions *require* access to
`SomeType`'s full definition?
Overall, I don't think your proposal works if you require the
expression to be able to use the derived class as though it were a
complete class. And if you take that out... how useful is this
functionality? After all, 2 out of 3 of your examples require the
derived class to be complete. If you take those away, all you're left
with is preventing a class from being the base class of anything but
some specific set of classes.
And is that *really* important enough to ask for a whole language feature?
Received on 2020-07-11 10:56:34