You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带throw()标记的函数在C++17下的不完全类型错误解决办法咨询

问题与解决方法

问题场景

现有如下C++代码:

测试函数

int ExampleFunction(int x, int y, double z) throw()
{ 
    return 0;
}

参数类型提取模板

#include <tuple>

template<typename Func>
struct MyGetFunctionParamType;

template <typename Ret, typename... Args>
struct MyGetFunctionParamType<Ret(Args...)> {
    using types = std::tuple<Args...>;
};

使用方式

using TypesOfParams = MyGetFunctionParamType<ExampleFunction>::types;
using ThirdParamType = std::tuple_element_t<2, TypesOfParams>;
auto value = ThirdParamType(addrSize(addr));

这段代码在C11中可正常编译,但在C17下编译报错:

incomplete type is not allowed function "ExampleFunction" is not a type name

已知移除throw()后代码可正常编译,但希望找到无需显式移除throw()的解决方法。

原因分析

在C中,函数的异常规范是其类型的一部分。C17弃用了throw()这类动态异常规范,但仍会将其视为函数类型的组成部分。原模板仅特化了不带异常规范的函数类型,无法匹配带throw()的函数类型,导致编译器认为MyGetFunctionParamType<ExampleFunction>是未完全定义的类型,从而报错。

解决方法

为模板添加支持带throw()异常规范的函数类型的特化,同时可额外支持C++11及以后的noexcept相关规范,确保兼容性:

修改后的模板代码:

#include <tuple>

template<typename Func>
struct MyGetFunctionParamType;

// 匹配不带异常规范的函数类型
template <typename Ret, typename... Args>
struct MyGetFunctionParamType<Ret(Args...)> {
    using types = std::tuple<Args...>;
};

// 匹配带throw()动态异常规范的函数类型
template <typename Ret, typename... Args>
struct MyGetFunctionParamType<Ret(Args...) throw()> {
    using types = std::tuple<Args...>;
};

// 匹配带noexcept的函数类型
template <typename Ret, typename... Args>
struct MyGetFunctionParamType<Ret(Args...) noexcept> {
    using types = std::tuple<Args...>;
};

// 匹配带常量表达式的noexcept(...)函数类型
template <typename Ret, typename... Args, bool NoexceptValue>
struct MyGetFunctionParamType<Ret(Args...) noexcept(NoexceptValue)> {
    using types = std::tuple<Args...>;
};

修改后,原使用代码无需改动即可在C17中正常编译,同时兼容C11环境。

内容的提问来源于stack exchange,提问作者Iván Ayala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 22:20:05