如何为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
相关产品推荐
相关产品推荐

