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

使用成员函数时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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:52:51