Search code examples
c++function-pointersstd-function

How to assign different methods (member functions) with different return types to a variable defined as auto?


I need to assign different methods (member functions) with different return types to a variable defined as auto variable. So the following code that returns the same data type is working as expected:

#include <iostream>

// Function pointers
int add(int a, int b) {
    return a + b;
}

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

// Define a type for function pointer
using OperationFunc = int (*)(int, int);

int main() {
    // Using auto with function pointers
    auto operation = add;
    std::cout << "Result of addition: " << operation(5, 3) << std::endl;

    operation = subtract;
    std::cout << "Result of subtraction: " << operation(5, 3) << std::endl;

    // Using auto with lambda functions
    auto multiply = [](int a, int b) { return a * b; };
    std::cout << "Result of multiplication: " << multiply(5, 3) << std::endl;

    return 0;
}

But when i try to make it more general like below

#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;

    // Assigning member functions to auto variable using std::function and lambdas
    auto operation = [&obj](auto func, auto... args) {
        return func(obj, args...);
    };

    // Using auto variable to call different member functions with different return types
    std::cout << "Result of addition: " << operation(&MyClass::add, 5, 3) << std::endl;
    std::cout << "Result of multiplication: " << operation(&MyClass::multiply, 5.5, 3.0) << std::endl;

    return 0;
}

I get the following error code.

> 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) (...)’

Any suggestion or hint how to fix it?


Solution

  • Your error is not about using different function types, it's about calling member function incorrectly. It even tells you the correct syntax you should be using:

    error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘func (...)’, e.g. ‘(... ->* func) (...)’    
    

    Prefer using std::invoke since C++17:

    auto operation = [&obj](auto func, auto... args) {
        return std::invoke(func, obj, std::forward<decltype(args)>(args)...);
    };
    

    If you cannot use C++17, you have to use the ugly "member access through pointer to member" syntax:

    auto operation = [&obj](auto func, auto... args) {
        return (obj.*func)(std::forward<decltype(args)>(args)...);
    };
    

    See it online