19

I'm trying to figure out a way of how to be able to assign a function pointer to functions with different number of arguments.

I have a while loop which takes a number of different functions as a conditional statement, so instead of writing multiple while loops with exactly the same code inside I'd like to have one with a function pointer. All the functions are of format bool f(...). I think some code will best illustrate what I mean:

int a, b, c, d;
MyClass* my_class;

typedef bool (MyClass::*my_fun_t)();
my_fun_t my_fun;

if (condition1)
    my_fun = &MyClass::function_one();
else if (condition2)
    my_fun = &MyClass::function_two(a, b);
else if (condition3)
    my_fun = &MyClass::function_three(a, b, c);
else if (condition4)
    my_fun = &MyClass::function_four(a, b, c, d);

while ((my_class->*my_fun)()) 
{ ... }

Now this obviously doesn't work because the functions have different signatures. Is it at all possible to make it work in a similar fashion? Are functoids something I should look at?

3
  • How would you know how to apply that function pointer if you don't know how many arguments it takes? Commented Jun 14, 2012 at 16:30
  • Note that your syntax of assignment to a function pointer is invalid anyway, you are invoking the functions, taking the result, getting a pointer to its temporary storage, and assign that to the function pointer you declared beforehand. Commented Jun 14, 2012 at 16:31
  • Yeah I know it's not quite a valid syntax. It just shows the idea. Commented Jun 14, 2012 at 16:32

4 Answers 4

9

You could use std::function<> and std::bind().

#include <functional>

using std::placeholders::_1;

typedef std::function<bool(MyClass&)> my_fun_t;
my_fun_t my_fun;

if (condition1)
    my_fun = std::bind(&MyClass::function_one, _1);
else if (condition2)
    my_fun = std::bind(&MyClass::function_two, _1, a, b);
else if (condition3)
    my_fun = std::bind(&MyClass::function_three, _1, a, b, c);
else if (condition4)
    my_fun = std::bind(&MyClass::function_four, _1, a, b, c, d);

while (my_fun(my_class)) { ... }

These assumes you will use C++11. If you can't use C++11 but can use TR1, replace all std:: with std::tr1::. There is also a Boost implementation.

Sign up to request clarification or add additional context in comments.

2 Comments

Excellent, thanks. I can't use C++11. Any reason to prefer tr1 over boost (which I'm using anyway)?
@Marian TR1 is built into the standard library, boost is not.
6

This works for me:

#include <iostream>
#include <cstdarg>

using namespace std;

class MyInterface
{
public:
    virtual bool func(int argc, ...) = 0;
};

class MyImpl : public MyInterface
{
public:
    virtual bool func(int argc, ...);
};

bool MyImpl::func(int argc, ...)
{
    va_list varargs;
    va_start(varargs,argc);
    cout << "Arguments passed:" << endl;
    for(int i = 0; i < argc; ++i)
    {
        // expect double values
        double val = va_arg(varargs,double);
        cout << val << endl;
    }
    va_end(varargs);
    return true;
}

typedef bool (MyInterface::*MyFunc)(int, ...);

int main() {

    MyImpl impl;
    MyInterface* interface = &impl;
    MyFunc pfunc = &MyInterface::func;

    if(!(interface->*pfunc)(2,double(3.14),double(2.72)))
    {
        return 1;
    }
    return 0;
}

Output:

Arguments passed:
3.14
2.72

Obviously you CAN declare and use function pointers for (member-)functions using variable arguments.

Comments

3

You want std::function, a polymorphic function object, and std::bind to create function objects by binding arguments to the parameters of other functors.

If you can't use C++11, then boost::function and boost::bind are equivalent, although slightly more restrictive.

std::function<bool()> my_fun;

if (condition1)
    my_fun = std::bind(&MyClass::function_one, my_class);
else if (condition2)
    my_fun = std::bind(&MyClass::function_two, my_class, a, b);
else if (condition3)
    my_fun = std::bind(&MyClass::function_three, my_class, a, b, c);
else if (condition4)
    my_fun = std::bind(&MyClass::function_four, my_class, a, b, c, d);

while (my_fun()) 
{ ... }

2 Comments

If you can use C++ 11 then you can also use lambda functions and pull the variables from the enclosing lexical scope. Whichever you prefer, I guess.
@user268396: Probably. For the time being, I'm stuck with a compiler that doesn't support lambdas, so I don't know much about them.
2

I'm trying to figure out a way of how to be able to assign a function pointer to functions with different number of arguments.

You can’t. Function pointers are specific to one function signature. This is entirely logical: how would you invoke such a function? (Yes, C allows invoking functions without specifying in their declaration how many parameters the function has, but this doesn’t work in C++ since it subverts the type system.)

Are functoids something I should look at?

Generally yes, but they don’t solve this problem.

3 Comments

Hmm, but just the 'signature' of a function with variable arguments is still unique, isn't it? The '...' variable arguments part is at least just a camouflage of 'va_list' used inside the functions implementation. Invoking such a function through a function pointer wouldn't (shouldn't) differ anyhow from invoking such function in the usual way (with a variable list of arguments).
@g-makulik Variable arguments work, but that’s a specific signature, it’s not the same as binding to different function signatures.
Ahh, I see your point!. But the OP didn't mention binding explicitely (may be I read his 'pseudo' code wrong). Using interface definitions (polymorphism) it might still be possible to achieve what the OP wants (intended).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.