使用成员函数时std::result_of编译失败的解决方法咨询
修复C++11中std::result_of的编译错误
首先,你的编译错误核心原因是**std::result_of的使用方式完全不符合C++11的规则**,再加上GetBTypeFromAType是重载的非静态成员函数,双重问题导致模板参数推导失败:
- 非静态成员函数必须依赖类对象(或指针)才能调用,
std::result_of需要明确这个调用上下文; - 重载函数无法直接通过函数名推导类型,编译器不知道你要指向哪一个重载版本。
最优解决方案:用decltype替代std::result_of(直观且解决重载歧义)
在C++11中,我们可以用decltype结合std::declval直接推导成员函数调用的返回类型,这种写法更清晰,完美适配重载场景。
修改你的Func模板代码如下:
template <typename AType> void Func(AType a) { // 用decltype推导当前对象调用成员函数后的返回类型 using BType = decltype(this->GetBTypeFromAType(std::declval<AType>())); std::cout << "Func called with " << GetTypeName<AType>() << " and got " << GetTypeName<BType>() << std::endl; }
为什么这个写法能工作?
std::declval<AType>():在编译期模拟生成一个AType类型的临时对象,只用于类型推导,不会产生实际运行代码;this->GetBTypeFromAType(...):明确绑定当前类对象,编译器会自动根据AType的类型匹配对应的重载函数;decltype(...):直接获取整个函数调用表达式的返回类型,作为BType的定义。
完整修复后的代码
#include <iostream> #include <typeinfo> #include <cxxabi.h> #include <memory> #include <utility> // 引入std::declval的头文件 template <class T> std::string GetTypeName() { std::unique_ptr<char, void(*)(void*)> name{ abi::__cxa_demangle(typeid(T).name(), 0, 0, nullptr), std::free }; return name.get(); } struct A { struct AA {}; struct AB {}; struct AC {}; struct BA {}; struct BB {}; struct BC {}; BA GetBTypeFromAType(AA a) { return BA(); } BB GetBTypeFromAType(AB a) { return BB(); } BC GetBTypeFromAType(AC a) { return BC(); } template <typename AType> void Func(AType a) { using BType = decltype(this->GetBTypeFromAType(std::declval<AType>())); std::cout << "Func called with " << GetTypeName<AType>() << " and got " << GetTypeName<BType>() << std::endl; } }; int main() { A a; A::AA aa; A::AB ab; A::AC ac; a.Func(aa); a.Func(ab); a.Func(ac); return 0; }
编译验证
用你原来的命令重新编译:
g++ -std=c++11 test.cpp -o test; ./test
会输出预期结果:
Func called with A::AA and got A::BA Func called with A::AB and got A::BB Func called with A::AC and got A::BC
额外说明:如果一定要用std::result_of怎么办?
如果你坚持要用std::result_of,需要强制指定成员函数指针的具体重载版本,但这种写法会失去模板的通用性,不推荐。例如针对AA类型的硬编码写法:
using BType = typename std::result_of<decltype(static_cast<BA(A::*)(AA)>(&A::GetBTypeFromAType))(A*, AType)>::type;
这种方式需要为每个AType特化,违背了模板的设计初衷,所以更推荐decltype的方案。
内容的提问来源于stack exchange,提问作者e271p314
相关产品推荐
相关产品推荐

