Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assign pointer to a function the address of a pointer to function object

Is it possible in C++? For example I have a pointer to a function that takes no parameters and its return type is void:

void (*f)();

and and a function object:

class A
{
public:
    void operator()() { cout << "functor\n"; }
};

Is it possible to assign to f the address of an A object? And when I call f() to call the A functor?

I tried this but it doesn't work:

#include <iostream>
using namespace std;

class A
{
public:
    void operator()() { cout << "functorA\n"; }
};

int main()
{
    A ob;
    ob();
    void (*f)();
    f = &ob;
    f();       // Call ob();
    return 0;
}

I get C:\Users\iuliuh\QtTests\functor_test\main.cpp:15: error: C2440: '=' : cannot convert from 'A *' to 'void (__cdecl *)(void)' There is no context in which this conversion is possible

Is there any way to achieve this?

like image 666
Jacob Krieg Avatar asked Feb 01 '13 09:02

Jacob Krieg


People also ask

How do you assign a pointer to a function?

int foo(int); Here foo is a function that returns int and takes one argument of int type. So as a logical guy will think, by putting a * operator between int and foo(int) should create a pointer to a function i.e. int * foo(int);

How do you assign a pointer to an address?

You need to initialize a pointer by assigning it a valid address. This is normally done via the address-of operator (&). The address-of operator (&) operates on a variable, and returns the address of the variable. For example, if number is an int variable, &number returns the address of the variable number.

Can you assign a pointer to a pointer?

3) Pointer AssignmentPointer assignment between two pointers makes them point to the same pointee. So the assignment y = x; makes y point to the same pointee as x . Pointer assignment does not touch the pointees. It just changes one pointer to have the same reference as another pointer.

How do you assign a pointer to a function in C++?

We declare the function pointer, int (*funcptr)(int,int) , and then store the address of the add() function in funcptr in the preceding program. This means that the address of the add() method is stored in funcptr . We can now use funcptr to invoke the add() method.


4 Answers

If you use C++11, could use std::function

#include <functional>

std::function<void()> f;

int main()
{
    A ob;
    ob();

    f = ob;    // f refers to ob
    f();       // Call ob();
    return 0;
}
like image 39
billz Avatar answered Sep 30 '22 07:09

billz


How about some workaround like this:

Basically you want to have a common way of calling member functions and functions. Then maybe you could create a wrapper that would represent a generic pointer to either a function or member function. Let's say you have Base class and you want to be able to invoke operator() of all derived classes. Then you also have a function() that you want to invoke as well:

class Base
{
public:
    virtual void operator()() = 0;
};

class A : public Base
{
public:
    void operator()(){ std::cout << "A()" << std::endl; }
};

void function()
{
    std::cout << "function" << std::endl; 
}

If you create an wrapper that allows you to construct your custom pointer (MyFncPtr):

typedef void (Base::*BaseFncPtr)();
typedef void (*FncPtr)();

class MyFncPtr
{
public:
    MyFncPtr(FncPtr f) : fnc(f), baseObj(NULL), baseFnc(NULL) { }
    MyFncPtr(BaseFncPtr fPtr, Base* objPtr) : baseFnc(fPtr), baseObj(objPtr), fnc(NULL)  { }
    void invoke()
    {
        if (baseObj && baseFnc)
            (baseObj->*baseFnc)();
        else if (fnc)
            fnc();
    }

private:
    BaseFncPtr baseFnc;
    Base* baseObj;
    FncPtr fnc;
};

you could achieve it like this:

A a;
MyFncPtr myPtr(&Base::operator(), &a);
myPtr.invoke();
MyFncPtr myPtr2(function);
myPtr2.invoke();

outputs:

A()
function

Hope this helps :)

like image 35
LihO Avatar answered Sep 30 '22 08:09

LihO


You can't do it in the way you've specified, because:

  1. operator() must be a nonstatic function (standards requirement)
  2. a pointer to a non-static function must have an implicit parameter - the pointer to the class instance
  3. your call to f() does not give any indication on which instance of the object A your function is called

Using C++11 and std::function, as Stephane Rolland pointed out, may do the trick - you'll be specifying the pointer to the object in the binding:

std::function<void(void)> f = std::bind(&A::operator(), &ob);

(See question on using std::function on member functions)

like image 109
DarkWanderer Avatar answered Sep 30 '22 08:09

DarkWanderer


Yes it's kind of possible using a C++1/C++0x feature, but to achieve this you should use the std::function which can address to the two types, functions and object functions.

#include <functional>

 class A
{
public:
    void operator()() { }
};

int main()
{
    std::function<void(void)> aFunction;
    A ob;

    aFunction = ob;

// or as another user said
// aFunction = std::bind(&A:operator(), &ob);

    aFunction();

    void (*f)();

    aFunction = f;

    aFunction();

    return 0;
}

and if you're stuck with C++03, you could play with std::mem_fun and std::ptr_fun

like image 36
Stephane Rolland Avatar answered Sep 30 '22 07:09

Stephane Rolland