带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
相关产品推荐
相关产品推荐

