How to add noexcept specifier to already defined function type?

Viewed 81

For example I have type:

typedef DWORD WINAPI HANDLER_FUNCTION_EX (DWORD);

And I want:

static as_noexcept<HANDLER_FUNCTION_EX>::type my_func; // forward declaration
static_assert(noexcept(my_func(0)));

I got something like:

template<typename>
struct noexcept_trait;

// specialization to infer signature
template<typename Result, typename... Args>
struct noexcept_trait<Result(Args...)>
{
    using as_noexcept = Result(Args...) noexcept;
    using as_throwing = Result(Args...);
};
// since C++17 noexcept-specification is a part of the function type
// so first specialization won't match
template<typename Result, typename... Args>
struct noexcept_trait<Result(Args...) noexcept>
{
    using as_noexcept = Result(Args...) noexcept;
    using as_throwing = Result(Args...);
};

template<typename T>
using add_noexcept_t = typename noexcept_trait<T>::as_noexcept;
template<typename T>
using remove_noexcept_t = typename noexcept_trait<T>::as_throwing;

But this code creates totally new type and drops all additional info (calling convention, attributes e.g. [[deprecated]]). So it's not safe. How can I fix it?

1 Answers

Add

template<typename Result, typename... Args>
struct noexcept_trait<Result __stdcall(Args...)>
{
    using as_noexcept = Result __stdcall(Args...) noexcept;
    using as_throwing = Result __stdcall(Args...);
};

and similar elsewhere. But you should only do this if !is_same_v< void(*)(), void(__stdcall *)() >. If __stdcall does nothing on your platform, you'll get a conflict here.

Attributes are explicitly not part of the type system. [[deprecated]] applies to the type definition itself, not the thing being defined. The very use of that type to create the alias is [[deprecated]].

Related