Date: Wed, 28 May 2025 11:55:37 -0400
On Wed, May 28, 2025 at 10:13 AM Howard Hinnant via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> On May 28, 2025, at 5:36 AM, Frederick Virchanza Gotham via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
> >
> > There are times when I'm writing template code and I end up with
> > 'noexcept' specifications [...]
> > when what I really want is that 'T' would be some sort of class whose
> > methods never throw.
> >
> > Would it be helpful at all to be able to mark a class or an individual
> > object as 'noexcept'? Maybe something like:
> >
> > class noexcept MyClass { . . . };
>
> Sometimes part of a type’s API is a member function, and sometimes a
> namespace scope function. E.g.: operator==.
> I’m concerned that if a type is marked noexcept that it might raise
> confusion for such namespace scope functions. They may be assumed to be
> part of the API of a type, but not be implacted by this type’s noexcept
> qualification.
>
See also P2350 "`constexpr class`" (2021, now apparently abandoned, which I
think is a good outcome):
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2350r2.pdf
It has the same problem: just because *most* of a class's *members* are
constexpr (resp. consteval, noexcept, noreturn, whatever) is no reason to
mark the "whole class" with that modifier. That just makes maintenance more
tedious, for no actual benefit. Or to put it another way: the proposed
feature is a benefit to *programming* (a.k.a. code golf of a single
unchanging artifact), but not to *software engineering* (a.k.a. maintenance
over time).
P2350R2 §6.1 talks about applying `noexcept` to a whole class in the same
way:
> noexcept acts differently than constexpr or final. Should I, as a
> developer, do something that is not allowed in, for example, a constexpr
> context the compiler gives me an error. Should I invoke a throwing function
> in a noexcept member function, I end up with a runtime error. It seems
> less desirable to me to create implicit noexcept member functions.
(P2350R2 also made a bogus comparison to `final`: "This paper proposes to
introduce a way of marking all member functions in a class as `constexpr`
with a single specifier in the *class-head*, like we can already do it
with `final`." However, that's a mistaken understanding of `final`. On a
single method, `final` means "you may not *override* me." On a class type,
`final` means "you may not *derive from* me," regardless of whether you
override any of my methods or not. That is:
class A final { virtual int f(); };
is fundamentally a different kind of thing from
class A { virtual int f() final; };
in that the latter permits
class B : public A {};
and the former does not. So `final` was never prior art for "applying a
keyword to all the members of a class." A final class is fundamentally
different from a final method.)
–Arthur
std-proposals_at_[hidden]> wrote:
> On May 28, 2025, at 5:36 AM, Frederick Virchanza Gotham via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
> >
> > There are times when I'm writing template code and I end up with
> > 'noexcept' specifications [...]
> > when what I really want is that 'T' would be some sort of class whose
> > methods never throw.
> >
> > Would it be helpful at all to be able to mark a class or an individual
> > object as 'noexcept'? Maybe something like:
> >
> > class noexcept MyClass { . . . };
>
> Sometimes part of a type’s API is a member function, and sometimes a
> namespace scope function. E.g.: operator==.
> I’m concerned that if a type is marked noexcept that it might raise
> confusion for such namespace scope functions. They may be assumed to be
> part of the API of a type, but not be implacted by this type’s noexcept
> qualification.
>
See also P2350 "`constexpr class`" (2021, now apparently abandoned, which I
think is a good outcome):
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2350r2.pdf
It has the same problem: just because *most* of a class's *members* are
constexpr (resp. consteval, noexcept, noreturn, whatever) is no reason to
mark the "whole class" with that modifier. That just makes maintenance more
tedious, for no actual benefit. Or to put it another way: the proposed
feature is a benefit to *programming* (a.k.a. code golf of a single
unchanging artifact), but not to *software engineering* (a.k.a. maintenance
over time).
P2350R2 §6.1 talks about applying `noexcept` to a whole class in the same
way:
> noexcept acts differently than constexpr or final. Should I, as a
> developer, do something that is not allowed in, for example, a constexpr
> context the compiler gives me an error. Should I invoke a throwing function
> in a noexcept member function, I end up with a runtime error. It seems
> less desirable to me to create implicit noexcept member functions.
(P2350R2 also made a bogus comparison to `final`: "This paper proposes to
introduce a way of marking all member functions in a class as `constexpr`
with a single specifier in the *class-head*, like we can already do it
with `final`." However, that's a mistaken understanding of `final`. On a
single method, `final` means "you may not *override* me." On a class type,
`final` means "you may not *derive from* me," regardless of whether you
override any of my methods or not. That is:
class A final { virtual int f(); };
is fundamentally a different kind of thing from
class A { virtual int f() final; };
in that the latter permits
class B : public A {};
and the former does not. So `final` was never prior art for "applying a
keyword to all the members of a class." A final class is fundamentally
different from a final method.)
–Arthur
Received on 2025-05-28 15:55:54