Casting a tr1::function to a void* - c++

I have the following tr1::function prototype that I am trying to cast to a void*:
typedef std::tr1::function<cv::Mat (const cv::Mat,const void*)> preprocessingFunc;
In this function I am storing it in a vector that contains structures denoting the type of function and the pointer to the function:
void ImageGraph::addNode(preprocessingFunc func)
{
NodeFunction nodeFunction = { typeid(func), (void*)func };
//nodes.push_back(nodeFunction);
}
The error I get:
ImagePipeline.cpp: In member function ‘void IP::ImageGraph::addNode(IP::preprocessingFunc)’:
ImagePipeline.cpp:32: error: invalid cast from type ‘IP::preprocessingFunc’ to type ‘void*’
/usr/include/c++/4.2.1/typeinfo:135: error: ‘std::type_info::type_info(const std::type_info&)’ is private
ImagePipeline.cpp:32: error: within this context
Is it possible to cast this function type to a pointer (void*)? If not, is there a better way to achieve what I am doing?
For clarity I am storing function pointers to call at later dates, and their are currently 3 types of function pointers, however I would like to store them all in the same vector.

A pointer to a member function can not be stored in a function pointer, because, essentially, a member function has a hidden argument (the "this" pointer).
There are two solutions: Either a real "pointer to member function" (which requires the correct type of function pointer), or make the function static, and pass in the object itself as a pointer (e.g. a void).
To me, this seems like kind of an odd solution, and I would think there are better solutions, such as using an interface class, and add your interface objects as "nodes", perhaps?
For a bit more on "pointer to member function", have a look here:
http://www.parashift.com/c++-faq/fnptr-vs-memfnptr-types.html
But given the comment below, you are actually trying to store an object in a pointer. That's similar to (void *)3.1415926; - it doesn't make sense. You probably shouldn't use void * here, but something else, such as pointer to function<> [and change your addNode to take a pointer to a preprocessingFunc object].

You're approaching it from the wrong end, it seems. Why are you using void* ? You state that you have " currently 3 types of function pointers". To store callable things, use tr1::function<>. It can be initialized from most reasonable sources: function pointers, bound pointers to member functions, functors, and obviously other tr1::functions

Related

Why my class keeps reseting and doesnt keep my changes [duplicate]

A simple question for which I couldn't find the answer here.
What I understand is that while passing an argument to a function during call, e.g.
void myFunction(type myVariable)
{
}
void main()
{
myFunction(myVariable);
}
For simple datatypes like int, float, etc. the function is called by value.
But if myVariable is an array, only the starting address is passed (even though our function is a call by value function).
If myVariable is an object, also only the address of the object is passed rather than creating a copy and passing it.
So back to the question. Does C++ pass a object by reference or value?
Arguments are passed by value, unless the function signature specifies otherwise:
in void foo(type arg), arg is passed by value regardless of whether type is a simple type, a pointer type or a class type,
in void foo(type& arg), arg is passed by reference.
In case of arrays, the value that is passed is a pointer to the first element of the array. If you know the size of the array at compile time, you can pass an array by reference as well: void foo(type (&arg)[10]).
C++ always gives you the choice: All types T (except arrays, see below) can be passed by value by making the parameter type T, and passed by reference by making the parameter type T &, reference-to-T.
When the parameter type is not explicitly annotated to be a reference (type &myVariable), it is always passed by value regardless of the specific type. For user-defined types too (that's what the copy constructor is for). Also for pointers, even though copying a pointer does not copy what's pointed at.
Arrays are a bit more complicated. Arrays cannot be passed by value, parameter types like int arr[] are really just different syntax for int *arr. It's not the act of passing to a function which produces a pointer from an array, virtually every possible operation (excluding only a few ones like sizeof) does that. One can pass a reference-to-an-array, but this explicitly annotated as reference: int (&myArray)[100] (note the ampersand).
C++ makes both pass by value and pass by reference paradigms possible.
You can find two example usages below.
http://www.learncpp.com/cpp-tutorial/72-passing-arguments-by-value/
http://www.learncpp.com/cpp-tutorial/73-passing-arguments-by-reference/
Arrays are special constructs, when you pass an array as parameter, a pointer to the address of the first element is passed as value with the type of element in the array.
When you pass a pointer as parameter, you actually implement the pass by reference paradigm yourself, as in C. Because when you modify the data in the specified address, you exactly modify the object in the caller function.
In C++, types declared as a class, struct, or union are considered "of class type". These are passed by value or you can say a copy using copy constructor is passed to the functions. This is pretty evident when we implement binary trees wherein you almost always have a Node * type of param in the recursive function acting on the binary tree. This is so as to facilitate modification of that node. If the node were to be passed as is (i.e not being a pointer type), the modifications to the nodes would have been to the local copy. Even in the case of vectors, while passing a copy of vectors is passed to the functions, to avoid which we use a reference &.
C++ passes arguments that are no pointers (int*) or references (int&) by value. You cannot modify the var of the calling block in the called function. Arrays are pointers.

Is it possible to call a method pointer with a void* pointer to the object

I have a struct, that contains a void* pointer to an object and a function pointer to some method of that object's class. I don't (and can't) have information of that objects' class, so I need a void*. I tried to call the method by this:
object->*function(args)
When I try to compile this with msvc I get two errors: C2296 and C2297
C2296 states, that the "->" is invalid because the left operand is invalid because it is of type "void"
C2297 states the same, but with the right operand and type "bool"
Is it possible to call a method pointer with a void* pointer to the object
No, it is not. More generally, you cannot indirect through a pointer to void at all.
Pointer to void must be casted to an pointer to object type that is compatible with the pointer to member function.
I don't (and can't) have information of that objects' class
If you know that the type of the object is compatible with the pointer to member function, then you should know what that type is. If you don't know the type, then you don't know that it's compatible and thus cannot call the pointer to member function.

How can I get rid of this reinterpret_cast, or is this usage OK?

I have a template member function with this signature:
template<typename T> void sync(void (*work)(T*), T context);
It can be called with a pointer to a function that accepts an argument of type T*. context is passed to that function. The implementation is this:
template<typename T> void queue::sync(void (*work)(T*), T context) {
dispatch_sync_f(_c_queue, static_cast<void*>(&context),
reinterpret_cast<dispatch_function_t>(work));
}
It uses reinterpret_cast<> and it works. The problem is that the standard doesn't define it very well and it is very dangerous. How can I get rid of this? I tried static_cast but that gave me a compiler error:
static_cast from void (*)(std::__1::basic_string<char> *) to dispatch_function_t (aka void (*)(void *)) is not allowed.
dispatch_function_t is a C type and is the same as void (*)(void*).
I'm not sure I was clear enough. What dispatch_sync_f does is it calls a given callback function and passes the given context parameter to that callback function. (It does that on another thread, although that is out of the scope of this question.)
The reason this is not supported by static_cast is because it is
potentially unsafe. While a std::string* will convert implicitely to
a void*, the two are not the same thing. The correct solution is to
provide a simple wrapper class to your function, which takes a void*,
and static_casts it back to the desired type, and pass the address of
this wrapper function to your function. (In practice, on modern
machines, you'll get away with the reinterpret_cast, since all
pointers to data have the same size and format. Whether you want to cut
corners like this is up to you—but there are cases where it's
justified. I'm just not convinced that this is one of them, given the
simple work-around.)
EDIT: One additional point: you say that dispatch_function_t is a C type. If this is the case, the actual type if probably extern "C" void (*)(void*), and you can only initialize it with functions that have "C" linkage. (Again, you're likely to get away with it, but I've used compilers where the calling conventions were different for "C" and "C++".)
I guess, you are not only casting work to dispatch_function_t, but calling it through dispatch_function_t pointer, aren't you? Such cast itself is valid according to standard, but all you can do with a casted pointer is cast it back to original type. Still your approach should work with most compilers and platforms. If you'd like to implement it so it's more standard conforming you can make a wrapper for your context and work function like this:
template <typename T>
struct meta_context_t
{
T *context;
void (*work)(T*);
};
template <typename T>
void thunk(void *context)
{
meta_context_t<T> *meta_context = static_cast<meta_context_t<T> *>(context);
meta_context->work(meta_context->context);
}
template<typename T> void queue::sync(void (*work)(T*), T context) {
meta_context_t<T> meta_context =
{
&context,
work
};
dispatch_sync_f(_c_queue, static_cast<void*>(&meta_context),
thunk<T>);
}
I can't believe this works or you have a rather narrow definition of "this works" (e.g. you found one particular setup where it seems to do what you think it should do). I'm not clear what dispatch_sync_f() does but I think it is suspicious that it gets a pointer to the local variable context as parameter. Assuming this variable outlives the use of this pointer, there is still a subtle problem which won't get you on most platforms but does get you on some:
C and C++ calling conventions can be different. That is, you cannot cast a pointer to a C++ function to a pointer to a C function and hope for this to be callable. The fix to this problem - and your original question - is, of course, an extra level of indirection: don't dispatch to the function you get as argument but rather dispatch to a C function (i.e. a C++ function declared as extern "C") which takes its own context holding both the original context and the original function and calls the original function. The only [explicit] cast needed is the static_cast<>() restoring a pointer to your internal context from the void*.
Since you seem to implement a template you might need to use another indirection to get rid of this type: I don't thing function templates can be declared extern "C". So you would need to restore the original type somehow e.g. using a base class and a virtual function or something like std::function<void()> holding a readily callable function object doing this conversion (a pointer to this object would be your context).
I believe the cast to/from these two function pointer types is fine:
void(*)(void*)
void(*)(T*)
The problem is that you can't actually use the pointer that you have so cast. It's legal only to cast back to the original type (and those casts are reinterpret_cast, because these are unrelated types). From your code, I can't see how your actual callback function is defined. Why can't you accept a dispatch_function_t as your parameter for queue::sync, rather than casting it?
reinterpret_cast is guaranteed to work when converting from a type T * to void * and back. It is, however, not acceptable to cast from or to a pointer to a base or derived class of T.
The type of work needs to be dispatch_function_t in this case, and the first order of business in that function needs to be the cast from void * to T *. Implicitly casting the argument by using a different argument type and casting the function type is not allowed.
Rationale: the standard allows different pointer representations for different types, as long as all pointer types can be converted to void * and back, so void * is the "most precise" pointer type. A conforming implementation is allowed to clear the bottom-order bits of an uint32_t * if sizeof(uint32_t) > sizeof(char) (i.e. sizeof(uint32_t) > 1) or even shift the pointer value if the machine instructions can utilize these pointers more effectively; on a machine with tagged or shifted pointer values the reinterpret_cast is not necessarily a no-op and needs to be written explicitly.

Clarification on pointer to non-static class member

When I need a pointer to member of class, I do as following
struct MyStruct
{
int foo();
};
int (MyStruct::*p)() = &MyStruct::foo;
My question is why do I need to use & operator to take the address which may be ignored if it were a static function. Also, I've heard pointer to members aren't really a pointer, Can someone clarify that?
If it's a static function, it works just as a regular non-member function pointer: the function name itself can be implicitly converted to a function pointer.
If it's a non-static member function, it's no longer the same thing as a non-member function:
It has a hidden this parameter;
In a multiple inheritance scenario, converting a pointer to one of the base classes may produce a pointer to a different address. This means that if the member function is inherited, the this pointer may need to be adjusted before the call. This already makes it impossible to use a pointer to store a pointer-to-member-function.
Raymond Chen wrote an interesting article about this with more details and examples.
why do I need to use & operator to take the address which may be
ignored if it were a static function
You are right, in the case of pointer to member function syntax ideally & can be omitted. I think, & syntax is there may be due to historical convention.
I've heard pointer to members aren't really a pointer, Can someone
clarify that?
That's not correct. The only difference is that they are pointer to member function. Since, class non-static member contain an implicit this pointer as their argument, they have a special signature. Also, they are not inter-convertible with normal function pointer with same signature.
In your code example, theoritically p is pointing to:
int MyStruct::foo (MyStruct* const);

member function pointer which returns same type of member function pointer

I'd like to declare a member function pointer in C++, that returns the same member function pointer type
This doesn't work:
class MyClass {
public:
typedef FunctionPtr (MyClass::*FunctionPtr)();
}
Does someone know a solution?
There's no way to achieve exactly that. In fact, member functions make no difference here: there's no way to declare an ordinary function that returns a pointer to its own function type. The declaration would be infinitely recursive.
In case of an ordinary function you can use the void (*)() type as an "universal" function pointer type (just like void * is often used for data types). For member function pointers that would be void (A::*)() type. You'd have to use reinterpret_cast for that purpose though. However, this usage (a round-trip conversion) happens to be the one when the behavior of reinterpret_cast is defined.
Of course, you'll be forced to use casts to convert the pointer to and from that type. AFAIK, there are elegant template-based solutions with an intermediate temporary template object that does the casting.
You might also want to take a look at this GotW entry.
P.S. Note, that using void * type as an intermediate type for function pointers is prohibited by the language. While such illegal use might appear to be "working" with ordinary function pointers, it has absolutely no chance to work with member function pointers. Member function pointers are normally non-trivial objects with size greater than the size of void * pointer.
AndreyT references the best answer at GotW #57, so I might as well replicate it here:
class MyClass {
public:
struct FunctionPtrProxy;
typedef FunctionPtrProxy (MyClass::*FunctionPtr)();
struct FunctionPtrProxy
{
FunctionPtrProxy(FunctionPtr pp ) : p( pp ) { }
operator FunctionPtr() { return p; }
FunctionPtr p;
}
}
What you're trying to do is not possible - the return type of the function is the type of the function itself, which is not yet known, so it leads to an infinite cycle.