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

如何为auto变量分配不同返回类型的类成员函数?

问题:将不同返回类型的类成员函数分配给auto变量的错误修复

可正常运行的同返回类型代码

当函数返回类型相同时,以下代码可以正常运行:

#include <iostream>

// 普通函数指针
int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;
}

// 定义函数指针类型
using OperationFunc = int (*)(int, int);

int main() {
    // 使用auto存储函数指针
    auto operation = add;
    std::cout << "加法结果: " << operation(5, 3) << std::endl;

    operation = subtract;
    std::cout << "减法结果: " << operation(5, 3) << std::endl;

    // 使用auto存储lambda
    auto multiply = [](int a, int b) { return a * b; };
    std::cout << "乘法结果: " << multiply(5, 3) << std::endl;

    return 0;
}

通用代码尝试及报错

尝试编写支持不同返回类型的类成员函数调用代码时,出现编译错误:

#include <iostream>
#include <functional>

class MyClass {
public:
    int add(int a, int b) {
        return a + b;
    }

    double multiply(double a, double b) {
        return a * b;
    }
};

int main() {
    MyClass obj;

    // 尝试用lambda封装成员函数调用
    auto operation = [&obj](auto func, auto... args) {
        return func(obj, args...);
    };

    // 调用不同返回类型的成员函数
    std::cout << "加法结果: " << operation(&MyClass::add, 5, 3) << std::endl;
    std::cout << "乘法结果: " << operation(&MyClass::multiply, 5.5, 3.0) << std::endl;

    return 0;
}

编译错误信息:

main.cpp: In instantiation of ‘main()::<lambda(auto:1, auto:2 ...)>
[with auto:1 = int (MyClass::*)(int, int); auto:2 = {int, int}]': 
main.cpp:24:53:   required from here main.cpp:20:20: error: must use
‘.*’ or ‘->*’ to call pointer-to-member function in ‘func (...)’, e.g.
‘(... ->* func) (...)’    20 |         return func(obj, args...);
      |                ~~~~^~~~~~~~~~~~~~ main.cpp: In instantiation of ‘main()::<lambda(auto:1, auto:2 ...)> [with auto:1 = double
(MyClass::*)(double, double); auto:2 = {double, double}]': 
main.cpp:25:59:   required from here main.cpp:20:20: error: must use
‘.*’ or ‘->*’ to call pointer-to-member function in ‘func (...)’, e.g.
‘(... ->* func) (...)’

修复方案

方案1:修正成员函数指针的调用语法

类成员函数指针必须绑定对象实例才能调用,需要使用.*运算符(针对对象实例)。修改lambda内的调用代码:

#include <iostream>
#include <functional>

class MyClass {
public:
    int add(int a, int b) {
        return a + b;
    }

    double multiply(double a, double b) {
        return a * b;
    }
};

int main() {
    MyClass obj;

    // 修正成员函数指针的调用方式
    auto operation = [&obj](auto func, auto... args) {
        return (obj.*func)(args...);
    };

    std::cout << "加法结果: " << operation(&MyClass::add, 5, 3) << std::endl;
    std::cout << "乘法结果: " << operation(&MyClass::multiply, 5.5, 3.0) << std::endl;

    return 0;
}

注意这里的括号不能省略,因为.*的优先级比函数调用低,必须用括号确保先绑定对象和成员函数指针,再传递参数。

方案2:使用std::invoke(C++17及以上)

如果需要更通用的调用方式(兼容普通函数、成员函数、lambda、函数对象等),可以用C++17引入的std::invoke,它会自动处理不同调用类型的语法:

#include <iostream>
#include <functional> // 包含std::invoke

class MyClass {
public:
    int add(int a, int b) {
        return a + b;
    }

    double multiply(double a, double b) {
        return a * b;
    }
};

int main() {
    MyClass obj;

    // 用std::invoke统一调用逻辑
    auto operation = [&obj](auto func, auto... args) {
        return std::invoke(func, obj, args...);
    };

    std::cout << "加法结果: " << operation(&MyClass::add, 5, 3) << std::endl;
    std::cout << "乘法结果: " << operation(&MyClass::multiply, 5.5, 3.0) << std::endl;

    // 也可以直接调用普通函数,兼容性更好
    auto add_func = [](int a, int b) { return a + b; };
    std::cout << "普通lambda调用结果: " << operation(add_func, 10, 20) << std::endl;

    return 0;
}

两种方案中,auto变量存储的都是lambda生成的闭包类型,编译器会根据每次调用的参数自动推导函数指针类型和返回值类型,完美适配不同返回类型的成员函数。

内容的提问来源于stack exchange,提问作者Ashkanxy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 13:26:02