Tuesday Coding Tip 29 — noexcept annotation

●5 ●23 ●87
calendar_today ago • schedule1 min read
— Originally published at medium.com

Tuesday coding tips are super short posts about various tidbits mainly from C++, but also from other programming languages I use. You can also follow the #TuesdayCodingTips hashtag on Mastodon and Linkedin.


Since C++11, users can annotate their functions as non-throwing and perform compile-time checks for non-throwing APIs so they can propagate it upwards or branch accordingly.

Note: Prior to C++11, one could use throw() to mark function as non-throwing or explicitly list types of exceptions that could be thrown from the function. If a function threw something not listed, std::unexpected would be invoked. This approach was not practical and was removed in C++17.

However, the annotation doesn’t imply that the function never throws or that the compiler will error out if it spots a contradiction. You might want to call a throwing function from a noexcept one simply because you know it won’t throw in your context.

#include <stdexcept>
#include <iostream>

template<class T>
concept HasFoo = requires(T& t)
{
    { t.foo() };
};

template<HasFoo T>
void bar(const std::string& str) noexcept
{
    if constexpr (noexcept(std::declval<T>().foo()))
        std::cout << str << " is noexcept" << std::endl;
    else
        std::cout << str << " is not noexcept" << std::endl;
}

struct A
{
    void foo() {}
};

struct B
{
    void foo() noexcept {}
};

int main()
{
    bar<A>("A");
    // output: A is not noexcept
    bar<B>("B");
    // output: B is noexcept
}

If you are wrong, any exception passing a noexcept boundary will transform into std::terminate, immediately killing your program without a guarantee of unwinding the stack.

#include <stdexcept>
#include <iostream>

void foo() noexcept
{
    throw std::runtime_error("ehlo");
}

int main()
{
    try
    {
        foo();
    }
    catch (const std::exception &e) {
        std::cout << e.what() << std::endl;
    }
}

// terminate called after throwing an instance of 'std::runtime_error'
//  what():  ehlo
// Program terminated with signal: SIGSEGV

The noexcept annotation gives the compiler a hint for optimizations (no stack unwinding) and it has documentation purposes for the users of your API.

#include <stdexcept>
#include <iostream>

template<class T>
concept HasFoo = requires(T& t)
{
    { t.foo() };
};

template<HasFoo T>
void bar(T t) noexcept(noexcept(std::declval<T>().foo()))
{
    // outer noexcept is an annotation that requires boolean parameter
    // inner noexcept is an operator that returns boolean
    t.foo();
}

struct A
{
    void foo() {}
};

struct B
{
    void foo() noexcept {}
};

int main()
{
    std::cout << "bar(A) is noexcept? " << noexcept(bar(A{})) << std::endl;
    // bar(A) is noexcept? 0
    std::cout << "bar(B) is noexcept? " << noexcept(bar(B{})) << std::endl;
    // bar(B) is noexcept? 1
}

For a better insight into optimizations enabled by noexcept, please refer to this article by Scott Meyers: https://aristeia.com/EC++11-14/noexcept%202014-03-31.pdf

Part 29 of 29 in Tuesday Coding Tips

1 Comment

0 votes
🔥 Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

Tuesday Coding Tip 06 - Explicit template instantiation

Jakub Neruda - Apr 7

Tuesday Coding Tip 02 - Template with type-specific API

Jakub Neruda - Mar 10

Tuesday Coding Tip 17 — Wrapping C APIs

Jakub Neruda - Jun 30

Tuesday Coding Tip 08 — Explicit template specialization

Jakub Neruda - Apr 21

Tuesday Coding Tip 05 - Object initialization in C++

Jakub Neruda - Mar 31
chevron_left
2k Points • 115 Badges
Brno, Czech Republic • linkedin.com/in/jakub-neruda
42Posts
35Comments
22Connections
Experienced C++ developer, team lead and hobby gamedev. I enjoy writing stuff about C++, clean code, clean architecture, and game development.

Related Jobs

View all jobs →

Commenters (This Week)

1 comment
1 comment
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!