On Sun, 7 Jun 2026 at 23:41, Michael Galuszka via Std-Proposals
<std-proposals@lists.isocpp.org> wrote:
> What I'd like feedback on
>
> 1. Is SG14/EWG broadly receptive to Layer 1 as a generalization of noexcept — that is, an effect specifier that is part of the function type, not an attribute?
To add more function-type (and pointer-to-function and reference-to-function) specifiers that lead to different template specializations,
and needs to be accommodated by various function wrappers, the added facility needs to cure cancer.
+1.
(And since this list's members tend to have trouble with the direction-of-causality here: what Ville's saying IIUC, and what I'm +1'ing, is not "...so you should proceed to make this facility cure cancer, so that it can be accepted" but rather "...so this facility does not have good enough cost/benefit ratio and it will not be accepted.")
Every time someone brings up the idea of a richer set of type qualifiers, I mention the CQual project. (Although I rarely remember its name; I keep wanting to call it "QualC," which is wrong.)
Reflection (on C++26 annotations) might be able to get you some of the benefit here.
The big problem I see in practice — the one that makes it really impossible for the compiler to help, and (merely) tedious for the user-programmer to program himself — is that it's not obvious how to combine the various qualifiers/attributes you might dream up. For example, suppose you were trying to verify stack usage, which is one of your Layer 2 examples. You might write
Does `f` use 1024 bytes of stack, 1024+256 bytes, 1024+512 bytes, or 1024+512+256 bytes?
Another difficulty is templates. Given
template<class T> void f() { T::g(); }
is that function non-allocating? Non-blocking? Well, it depends on what `T::g()` does. So perhaps we want a way to propagate these properties bottom-up through unannotated templates; or we want something like `noexcept(auto)`; or else we want a query language for them, which would be hella tedious and error-prone.
But vice versa, it seems to me that most of the benefit of these annotations would come from enforcing them top-down — "a nonblocking function must not call any function that is not itself nonblocking," for example.
Unfortunately then you have the problem that no function today is marked nonblocking! For example `htonl` is not marked nonblocking, so any function that calls `htonl` will be assumed to block. (Analogously, today, `htonl` is not noexcept, so any function that calls `htonl`
will be assumed to throw.)
And then you have the problem, probably, that in the Unix world just about every function could be blocking or could be nonblocking, depending on the state of the objects passed to it (e.g. the values of its bitmask arguments, e.g. whether a socket is in nonblocking mode or not). This can be worked around — the user-programmer just has to split each offending function into two wrappers and make sure they're used properly (custom qualifiers might help with that).
On the other hand, actual compilers that target embedded systems, like Green Hills MULTI, definitely already have reliable checkers for the complicated stuff like "stack usage." They actually know what the codegen looks like, which no source-level annotation can ever discover (because you need to actually codegen the instructions before you can see what the stack usage is). I dare say that's the right approach: start with a problem you can solve, and solve it, and see what the solution looks like. If you find that multiple vendors have solved the problem in similar ways, then think about whether it would help to standardize the solution.
HTH,
Arthur