【问题标题】:How to add noexcept specifier to already defined function type?如何将 noexcept 说明符添加到已定义的函数类型?
【发布时间】:2021-11-19 20:26:20
【问题描述】:

例如我有输入:

typedef DWORD WINAPI HANDLER_FUNCTION_EX (DWORD);

我想要:

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

我得到了类似的东西:

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;

但是这段代码创建了全新的类型并删除了所有附加信息(调用约定、属性,例如[[deprecated]])。所以不安全。我该如何解决?

【问题讨论】:

  • 你确定HANDLER_FUNCTION_EX()不是在扔吗?即使它是纯 C 函数,如果它可能间接调用另一个函数,则该函数可能会抛出异常。请参阅this question 以获得有趣的阅读。
  • @G.Sliepen HANDLER_FUNCTION_EX 只是函数类型名称。实际函数是my_func,用noexcept定义,所以肯定不会抛出。
  • 如果您的编译器扩展了类型系统以具有调用约定修饰符,您就不能添加更多的特化来处理这些情况吗?可以肯定的是,这很长,但并不难。
  • @DavisHerring __attribute__((stdcall))__stdcall 不是函数类型的一部分,因此所有特化都存在冲突(错误:已定义类模板)
  • @DavisHerring 它失败了,因为在 x64 模式下,msvc 将 __cdecl 视为 __stdcall。如果我选择 x86 目标,它们将被视为不同的类型。 devblogs.microsoft.com/oldnewthing/20200717-00/?p=103989

标签: c++ visual-c++ c++20


【解决方案1】:

添加

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

和其他地方类似。但只有在!is_same_v&lt; void(*)(), void(__stdcall *)() &gt; 时才应该这样做。如果__stdcall 在你的平台上什么都不做,你就会在这里遇到冲突。

属性明确不是类型系统的一部分。 [[deprecated]] 适用于类型定义本身,而不是被定义的事物。该类型创建别名的真正用途是[[deprecated]]

【讨论】:

    猜你喜欢
    • 2014-01-17
    • 2023-03-20
    • 2022-10-20
    • 2015-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-11
    • 2019-09-22
    相关资源
    最近更新 更多