Lambda参数与返回类型获取问题:Do函数编译失败排查
解决Lambda类型萃取在模板函数中的编译错误
这个问题的核心是C++模板中的依赖名称查找规则在搞鬼,我们一步步拆解来解决:
为什么main里正常,Do函数里报错?
在main函数中,traits是基于具体的lambda类型生成的(不依赖任何模板参数),编译器可以直接确定traits::arg是一个嵌套模板,所以traits::arg<1>::type能被正确解析。
但在模板函数Do中,traits是依赖于模板参数FuncType的依赖类型——编译器在实例化模板之前,无法确定traits::arg到底是一个模板还是普通成员变量/类型。这时候它会默认把arg当成非模板,于是arg<1>就会被错误解析成arg < 1(小于号比较),从而触发编译错误。
修复方案
只需要在访问依赖类型的嵌套模板时,加上template关键字明确告诉编译器:“这是个模板!”,同时配合typename标注后续的是类型:
修改后的Do函数代码如下:
template <typename FuncType> void Do(FuncType func) { typedef function_traits<decltype(func)> traits; // 添加template关键字,明确arg是嵌套模板 typename traits::template arg<1>::type x = 0; std::cout << GetTypeName<traits>() << std::endl; // 同样需要template和typename来解析arg<1>::type std::cout << GetTypeName<typename traits::template arg<1>::type>() << std::endl; }
解释两个关键字的作用
typename:用于声明traits::template arg<1>::type是一个类型名称(因为它依赖于模板参数,编译器无法提前确认)。template:用于声明arg是traits的嵌套模板成员,让编译器正确解析arg<1>的模板实例化语法,而不是当成比较操作。
现在用你原来的编译命令g++ -std=c++11 test.cpp -o test就能正常编译通过,运行结果和main函数中的输出一致。
内容的提问来源于stack exchange,提问作者e271p314
相关产品推荐
相关产品推荐

