How to transfer almost anything to a function in C ++ (or C)?

I need to pass something like a pointer that takes something as a parameter to a function. You know, something without a predefined type or a type that can take something like this:

void MyFunc( *pointer ); 

And then use it like:

 char * x = "YAY!"; MyFunc(x); int y = 10; MyFunc(&y); MyObj *b = new MyObj(); MyFunc(b); 

And I do not want to use templates, because basically I use C in my project. Is there anything that can be used here other than a function macro?

+4
source share
5 answers

In C ++, Boost.Any will allow you to do this in a safe way:

 void func(boost::any const &x) { // any_cast a reference and it // will throw if x is not an int. int i = any_cast<int>(x); // any_cast a pointer and it will // return a null pointer if x is not an int. int const *p = any_cast<int>(&x); } // pass in whatever you want. func(123); func("123"); 

In C, you should use the void pointer:

 void func(void const *x) { // it up to you to ensure x points to an int. if // it not, it might crash or it might silently appear // to work. nothing is checked for you! int i = *(int const*)x; } // pass in whatever you want. int i = 123; func(&i); func("123"); 

You seem to be against this, but I will recommend it anyway: if you use C ++, hug it. Do not be afraid of patterns. Things like Boost.Any and void pointers take place in C ++, but this is very small.

Update

Well, I make small signals - slots - the connection library is used with my gui toolkit. So that I can get rid of Ugly WNDPROC. I need these pointers for connections.

If you need multipurpose signals, Boost.Signals already provides a complete and proven implementation of signals / slots. You can use Boost.Bind (or std::bind if you have a C ++ 0x compiler) to connect member functions:

 struct button { boost::signal<void(button&)> on_click; } struct my_window { button b; my_window() { b.on_click.connect(std::bind(&my_window::handle_click, this, std::placeholders::_1)); } void handle_click(button &b) { } void simulate_click() { b.on_click(b); } }; 

If you need a simple callback, Boost.Function (or std::function , if you have a C ++ 0x compiler) will work well:

 struct button { std::function<void(button&)> on_click; } struct my_window { button b; my_window() { b.on_click = std::bind(&my_window::handle_click, this, std::placeholders::_1); } void handle_click(button &b) { } void simulate_click() { b.on_click(b); } }; 
+11
source

You can use a function that accepts void* , but you should be aware of pointer types that are not compatible with void* :

  • Pointers to functions:

     void MyFunc(void*); MyFunc(&MyFunc); // WRONG 
  • pointers to elements:

     void MyFunc(void*); struct A { int x; }; MyFunc(&A::x); // WRONG 

Although these pointers are not compatible with void* (even with casting, on some compilers), they themselves are data. Therefore, you can pass a pointer to a pointer:

 void MyFunc(void*); void (*pfn)(void*) = &MyFunc; MyFunc(&pfn); // ok struct A { int x; }; int A::*px = &A::x; MyFunc(&px); // ok 
+7
source

You can define a method as one void * argument. Of course, at this point you need to figure out what to do with the data (in terms of access to it or its casting).

 void MyFunc(void * ptr); 
+2
source

You can use:

 void MyFunc( void* p){} int g = 10; MyFunc( (void*)&g ); 
+1
source

void * is a way to do this. You can assign any type of pointer to and from void * . But in order to use a pointer in the called function, you will need to know the type so that you can create the corresponding local pointer or make it accordingly. You can encode a limited set of types as enumeration characters, and perhaps use a switch to select a type of behavior. But without a specific purpose or precedent, you can end up chasing your tail in search of a community that C has never intended for.

Another way would be to make a union to contain all the different types that you know.

 typedef union { int i; char c; float f; } vartype; 

Then, if the value can carry its own type identifier, it becomes a tag pool or variant record.

 typedef struct { enum type { INT, CHAR, FLOAT } type; vartype var; } varrec; 
0
source

All Articles