Trait to detect if a function type is maked noexcept
Asked Answered
K

2

7

I am wondering whether there would be a trick to simplify the writing of a trait to return whether a type is a noexcept function. Currently my implementation is the following, and it just lists all the possibilities, one by one. Could it be written in a simpler way using standard C++20?

// Default
template <class>
struct is_noexcept_function: std::false_type {};

// Variable template
template <class T>
inline constexpr bool is_noexcept_function_v
= is_noexcept_function<T>::value;

// Noexcept functions
template <class R, class... Args>
struct is_noexcept_function<R(Args...) noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args...) const noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args...) volatile noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args...) const volatile noexcept>: std::true_type {};

// Noexcept lvalue-ref-qualified functions
template <class R, class... Args>
struct is_noexcept_function<R(Args...) & noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args...) const & noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args...) volatile & noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args...) const volatile & noexcept>: std::true_type {};

// Noexcept rvalue-ref-qualified functions
template <class R, class... Args>
struct is_noexcept_function<R(Args...) && noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args...) const && noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args...) volatile && noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args...) const volatile && noexcept>: std::true_type {};

// Noexcept variadic functions
template <class R, class... Args>
struct is_noexcept_function<R(Args..., ...) noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args..., ...) const noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args..., ...) volatile noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args..., ...) const volatile noexcept>: std::true_type {};

// Noexcept lvalue-ref-qualified variadic functions
template <class R, class... Args>
struct is_noexcept_function<R(Args..., ...) & noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args..., ...) const & noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args..., ...) volatile & noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args..., ...) const volatile & noexcept>: std::true_type {};

// Noexcept rvalue-ref-qualified variadic functions
template <class R, class... Args>
struct is_noexcept_function<R(Args..., ...) && noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args..., ...) const && noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args..., ...) volatile && noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args..., ...) const volatile && noexcept>: std::true_type {};
Kumar answered 16/6, 2020 at 14:42 Comment(3)
Isn't this just std::is_nothrow_invocable?Himyarite
@Himyarite Except that to call it properly I think you need to specialize on all possible function variations, which brings you back to the exact same problem. If you manage to do it because I didn't think of something, I would like to see your answer.Kumar
This similar question: https://mcmap.net/q/394467/-stripping-all-qualifiers-from-a-function-type/5754656 makes it seem like you have to write all of those specialisationsFitted
N
1

There are two parts to your problem: detect whether the type is a function, then detect whether that function is noexcept. Unfortunately, there is no better way to detect whether a type is a function. Not even in C++20. You really do need to specialize for all combinations of const, volatile, and ref qualification.

This fact caused much frustration to at least one standard library implementer when noexcept became part of a function's type in C++17.

Nordgren answered 12/9, 2020 at 22:49 Comment(0)
R
0

See my own (free) solution here (production grade, fully documented). It's a full implementation of the ideas discussed in this post.

Download the code, add "TypeTraits.h" and "CompilerVersions.h" to your project, then do the following (noting that other ways exist to pass your function's type - see docs). Note that you don't have to explicitly #include "CompilerVersions.h", it's automatically #included in "TypeTraits.h".

#include "TypeTraits.h"
using namespace StdExt; // Everything's in this namespace
constexpr bool isNoexcept = IsNoexcept_v<decltype(YourFunction)>;
Resumption answered 17/5, 2023 at 0:0 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.