C++ Logo

std-proposals

Advanced search

[std-proposals] noexcept(static)

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Fri, 4 Sep 2026 11:51:09 +0100
If you mark a function as 'noexcept(false)', it is free to throw an
exception up to its caller.

If you mark a function as 'noexcept' or 'noexcept(true)', it will
never throw an exception up to its caller -- but only because
'std::terminate' gets called instead.

If you mark a function as 'noexcept(static)', it will never throw an
exception up to its caller -- because you'll get a compile-time error
if any statement inside the function body might throw.

In C++, when including a header from a C file, you usually do:

    extern "C" {
        #include "someClibrary.h"
    }

but now you can also do:

    extern "C" noexcept(static) {
        #include "someClibrary.h"
    }

This has the effect of sticking "noexcept(static)" on all functions
and all function pointers. And just in case you're worried about
nesting, you can turn off the nesting as follows, look closely for the
exclamation point:

    extern "C" noexcept(static) {
        #include "someClibrary.h"
        extern "C++" !noexcept(static) {
            #include "someCPlusPluslibrary.hpp"
        }
    }

Here's where I would use this new feature:
    (1) I would consistently mark destructors as 'noexcept(static)' --
as you don't want an exception being thrown while the stack is being
unwound.
    (2) When writing C++ code that uses a C library, you want to make
sure all resources get freed, because you don't want an exception to
be thrown between "OpenResource" and "CloseResource".
    (3) When calling a C++ function from C -- just for a little added
assurance that std::terminate won't get called.
    (4) On move-constructors and move-assignment operators. These get
marked 'noexcept' so that vector reallocation takes the 'move' path,
but you want to be sure that std::terminate doesn't get called.
    (5) On a coroutine promise's 'final_suspend'. The standard already
requires that 'co_await promise.final_suspend()' not be
potentially-throwing, so the compiler forces you to mark it 'noexcept'
-- but that check is on the declaration, not on the body.
'noexcept(static)' is what actually verifies it.

Here it is tested and working:

    https://godbolt.org/z/hE3e13Pvq

Here's the compiler patch:

    https://github.com/healytpk/gcc-thomas-healy/commit/noexcept_static

And here's the GodBolt copy-pasted:

    #include <new>

    void Func1(void) noexcept(static)
    {
        new int[64]; // fail to compile
    }

    void Func2(void) noexcept(static)
    {
        new(std::nothrow) int[64];
    }


    int main(void)
    {
        Func1();
        Func2();
    }

Received on 2026-09-04 10:51:27