ghiboz
ghiboz

Reputation: 7993

c++ void* to parameter to a function

I have this function in some library:

class myConsole
{
    void addCommand( std::string command, void* fn );
    ...
}

and in my class I have this function:

void myApp::TestFn( const std::vector<std::string> & args )
{
    // do something
}

in the same class I call this:

void myApp::initApp( )
{
    myConsole::getSingleton( ).addCommand( "FirstTest", &myApp::TestFn );
}

but this gives me this error:

error c2664 cannot convert parameter 2 from 'void(__thiscall myApp::*)(const std::vector<_Ty>&)' to 'void *'

how can I solve this?

thanks in advance!

Upvotes: 2

Views: 1568

Answers (3)

Aaron McDaid
Aaron McDaid

Reputation: 27123

You should avoid void*, especially when trying to use function pointers. I'm going to assume that you are looking only at member-function pointers in the myApp class, and that you are only interested in member-function pointers which take const std::vector<std::string> &args as an argument. This typedef will create the appropriate type and call it MemFunType

typedef void (myApp :: * MemFunType) (const std::vector<std::string> &);

Here is a complete example (on ideone), where there are two different member-functions you may be interested in, TestFn and TestFnBackwards. This example probably isn't very useful, but it gives some examples of member-function pointers.

#include<iostream>
#include<vector>
using namespace std;

struct myApp;

struct myConsole
{
        typedef void (myApp :: * MemFunType) (const std::vector<std::string> &);
            void addCommand( std::string command, MemFunType fn );
};

struct myApp {
        void TestFn( const std::vector<std::string> & args ) {
                cout << " TestFn" << endl;
                for(std :: vector<std::string> :: const_iterator i = args.begin(); i!=args.end(); i++) {
                        cout << *i << endl;
                }
        }
        void TestFnBackwards( const std::vector<std::string> & args ) {
                cout << " TestFnBackwards" << endl;
                for(std :: vector<std::string> :: const_reverse_iterator i = args.rbegin(); i!=args.rend(); i++) {
                        cout << *i << endl;
                }
        }
        static myApp & getSingleton();
} ma;
myApp& myApp :: getSingleton() {
        return ma;
}

void myConsole :: addCommand( std::string , MemFunType fn ) {
        vector<string> words;
        words.push_back("hello");
        words.push_back("world");
        myApp &ma = myApp :: getSingleton();
        (ma.*fn)(words); // execute the member on the singleton object, using the words as the argument.
}

int main() {
        myConsole m;
        m.addCommand( "FirstTest", &myApp::TestFn );
        m.addCommand( "FirstTest", &myApp::TestFnBackwards );
}

Upvotes: 1

Dacav
Dacav

Reputation: 14078

The problem here is that you are trying to pass a class method as it were a void * pointer. This cannot be done.

The right way of doing this is by using templates for the void addCommand (std::string, void *) method. Something like

class myConsole {
    template <typename T>
    void addCommand( std::string command, T f);
};

struct Callback {
    myApp &app;
    Callback (myApp &a) : app(a) {
    }
    void operator() (const std::vector<std::string> &args) {
        app.TestFn(args);
    }
};

void myApp::initApp( )
{
    myConsole::getSingleton( ).addCommand( "FirstTest", Callback(*this) );
}

This gives you the callback principle in C++, but I think you need something more flexible than this solution, since you actually want to choose automatically the command that will be executed by the callback (in this case TestFn).

Upvotes: 1

Fred Foo
Fred Foo

Reputation: 363507

You can't solve this. You can't reliably cast a function pointer to void * and back.

(I suggest you redesign the program and stay clear of void*; there's no real need for it in C++.)

Upvotes: 9

Related Questions