Here's some code from the PhysX examples:
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC,
reinterpret_cast<PxActor**>(&actors[0]), nbActors);
And then in the code of the getActors function they use it like this:
PxU32 NpScene::getActors(PxActorTypeFlags types, PxActor** buffer, PxU32 bufferSize, PxU32 startIndex=0) const
{
...
if ((types & PxActorTypeFlag::eRIGID_STATIC ) && mRigidActors[i]->is<PxRigidStatic>())
{
if (virtualIndex >= startIndex)
buffer[writeCount++] = mRigidActors[i];
virtualIndex++;
}
else if ((types & PxActorTypeFlag::eRIGID_DYNAMIC) && mRigidActors[i]->is<PxRigidDynamic>())
{
if (virtualIndex >= startIndex)
buffer[writeCount++] = mRigidActors[i];
virtualIndex++;
}
...
}
mRigidActors is defined as Ps::Array<PxRigidActor*>
The inheritance diagram looks like this:
So, my questions are:
I heard that the pointer to the parent class can point to the instance of the child class. Then, why do we need any casting at all? I tried, but without casting it doesn't work.
Is it safe to use reinterpret_cast as it is used here?
(I suppose yes, because it's just pointers conversion)
Is there a better solution?
I heard that the pointer to the parent class can point to the instance of the child class. Then, why do we need any casting at all? I tried, but without casting it doesn't work.
There is an implicit conversion from PxRigidActor* to PxActor* (a derived-to-base pointer conversion), but there is no such relationship between PxRigidActor** and PxActor**
Is it safe to use reinterpret_cast as it is used here? (I suppose yes, because it's just pointers conversion)
The cast is not itself unsafe, but it is undefined behaviour to dereference the pointer created by the cast.
Is there a better solution?
Define actors with an appropriate type in the first place, i.e.
std::vector<PxActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, actors.data(), nbActors);
You can then static_cast<PxRigidActor*> the elements of actors as needed.
reinterpret_cast<PxActor**>(&actors[0])
is casting the address of the first element of the vector, not casting the element itself.
Furthermore, the called function is treating the pointer as an array. That is, it is casting the .data() of the vector to a different type of element.
You would expect static_cast to be used when navigating between base/derived class references or pointers. But that highlights an issue: The cast might modify the address, if the base class instance is not at the beginning of the derived class! The reinterpet_cast avoids this and just changes the type without changing the value... but if such a value change was necessary, this code would not work right anyway. By casting the "out" parameter's address instead of the value in that address, the code has no idea that anything stored in that slot needs to be adjusted back to the real type.
Since he's casting a pointer to the pointer, the static_cast would not work directly in the same place. It's a double pointer, and that doesn't follow the rule of D* to B*. It would have to write the static_cast
as a reference cast, and then take the address of that. Off the top of my head, something like &static_cast<PxActor*&>(actors.data()) (that might have the same issue; I'd have to bang on it to get something working, probably not as a single expression; and I have no intention of trying to do that.)
My guess is that he converted a legacy C cast to reinterpet_cast and didn't think too much about it, or saw that only this one worked (in the same place as the legacy cast).
but why?
The code populates a contiguous collection of the base class pointer. It takes an out parameter instead of returning a vector, and the caller wants that vector defined as a derived type instead of the base type. Normally it should be just fine to keep it as the base class since the behavior is presumably polymorphic.
This is copying from different source collections, with identical code in each branch. It probably ought to be generic, or use the visitor pattern. That would avoid most of the type casting issues.
Related
From Programming Language Pragmatics, by Scott
For systems programming, or to facilitate the writing of
general-purpose con- tainer (collection) objects (lists, stacks,
queues, sets, etc.) that hold references to other objects, several
languages provide a universal reference type. In C and C++, this
type is called void *. In Clu it is called any; in Modula-2,
address; in Modula-3, refany; in Java, Object; in C#, object.
In C and C++, how does void * work as a universal reference type?
void * is always only a pointer type, while a universal reference type contains all values, both pointers and nonpointers. So I can't see how void * is a universal reference type.
Thanks.
A void* pointer will generally hold any pointer that is not a C++ pointer-to-member. It's rather inconvenient in practice, since you need to cast it to another pointer type before you can use it. You also need to convert it to the same pointer type that it was converted from to make the void*, otherwise you risk undefined behavior.
A good example would be the qsort function. It takes a void* pointer as a parameter, meaning it can point to an array of anything. The comparison function you pass to qsort must know how to cast two void* pointers back to the types of the array elements in order to compare them.
The crux of your confusion is that neither an instance of void * nor an instance of Modula-3's refany, nor an instance of any other language's "can refer to anything" type, contains the object that it refers to. A variable of type void * is always a pointer and a variable of type refany is always a reference. But the object that they refer to can be of any type.
A purist of programming-language theory would tell you that C does not have references at all, because pointers are not references. It has a nearly-universal pointer type, void *, which can point to an object of any type (including integers, aggregates, and other pointers). As a common but not ubiquitous extension, it can also point to any function (functions are not objects).
The purist would also tell you that C++ does not have a (nearly-)universal pointer type, because of its stricter type system, and doesn't have a universal reference type either.
They would also say that the book you are reading is being sloppy with its terminology, and they would caution you to not take any one such book for the gospel truth on terminological matters, or any other matters. You should instead read widely in both books and CS journals and conference proceedings (collectively known as "the literature") until you gain an "ear" for what is generally-agreed-on terminology, what is specific to a subdiscipline or a community of practice, and so on.
And finally they would remind you that C and C++ are two different languages, and anyone who speaks of them in the same breath is either glossing over the distinctions (which may or may not be relevant in context), decades out of date, or both.
Probably the reason is that you can take address of any variable of any type and cast it to void*.
It does by a silent contract that you know the actual type of object.
So you can store different kinds of elements in a container, but you need to somehow know what is what when taking elements back, to interpret them correctly.
The only convenience void* offers is that it's idiomatic for this, i.e. it's clear that dereferencing the pointer makes no sense, and void* is implicitly convertible to any pointer type. That is for c/
In c++ this is called type erasure techniques preferred. Or special types, like any (there is a boost version of this too.)
void* is no more just a pointer. Thus, it holds an address of an object (or an array and stuffs like that)
When your program is running, every variable should have it owns address in memory, right? And pointer is somethings point to that address.
In normal, each type of pointer should be the same type of object int b = 5; int* p = &b; for example. But that is the case you know what the type is, it means the specific type.
But sometimes, you just want to know that it stores somethings somewhere in memory and you know what "type" of that address, you can cast easily. For example, in OpenCV library which I am learning, there are a lot of functions where user can pass the arguments to instead of declaring global variables and most use in callback functions, like this:
void onChange(int v, void *ptr)
Here, the library does not care about what ptr point to, it just know that when you call the function, if you pass an address to like this onChange(5,&b) then you must cast ptr to the same type before dealing with it int b = static_cast<int*>(ptr);
Probably this explanation from Understanding pointers from Richard Reese will help
A pointer to void is a general-purpose pointer used to hold references to any data type.
It has two interesting properties:
A pointer to void will have the same representation and memory alignment as a pointer to char
A pointer to void will never be equal to another pointer. However, two void pointers assigned a NULL value will be equal.
Any pointer can be assigned to a pointer to void. It can then be cast back to its original pointer type. When this happens the value will be equal to the original pointer value.
This is illustrated in the following sequence, where a pointer to
int is assigned to a pointer to void and then back to a pointer to int
#include<stdio.h>
void main()
{
int num = 100;
int *pi = #
printf("value of pi is %p\n", pi);
void* pv = pi;
pi = (int*)pv;
printf("value of pi is %p\n", pi);
}
Pointers to void are used for data pointers, not function pointers
I need to call an API function which needs a struct-pointer as a parameter.
lets say its this struct
struct SomeObject{
double a;
double b;
}
and this function to call: func(SomeObject*)
The problem here is that I only have access to data as a custom struct but the same structure like SomeObject given as an vector.
struct CustomObject{
double a;
double b;
}
And the compiler is throwing errors because they are different parameters. cannot convert 'std::vector<CustomObject>' to 'SomeObect*' in argument passing. I tried already to pass the CustomObject as a pointer but its of course still a different Object.
Is there any chance to get this working what I am trying to do? And what could be a possible approach?
You can't pass a std::vector to a function that expects a pointer. If the function expects a pointer to an array, then you can get that pointer using std::vector::data
Now, that leaves us with the problem that the vector contains objects of a wrong type. The pointer returned by std::vector::data will be of type CustomObject* while you need SomeObject*. They're unrelated, but identical types and luckily, standard layout types. As long as those two requirements hold, that gives us the guarantee that the types have the same representation. Therefore, we can simply cast the pointer with reinterpret_cast:
func(reinterpret_cast<SomeObject *>(vec.data()));
The compiler is now showing 'cast away qualifiers'. It seems to have a problem with because CustomObject is currently a const.
I take that to mean that the vector is const, or it's a vector of const objects. In that case you shouldn't pass it's data to a function that takes a pointer to non-const. But if you know that the function will not modify the objects, despite taking a pointer to non-const, and you want to get rid of the compiler warning, then you must cast the constness away explicitly, using const_cast.
reinterpret_cast might have 'solved' the problem, but has made your code incredibly brittle. I'd really not recommend that approach.
Instead I'd manually construct a SomeObject from the CustomObject:
SomeObject x;
x.a = myCustomObj.a;
x.b = myCustomObj.b;
func(&x);
This also avoids the const issue. Don't even think about optimizations or efficiency at this stage. YAGNI.
func((SomeObject *)&obj[0]);
When reading about const_cast I came across sentences like the following:
Only the following conversions can be done with const_cast. In particular, only const_cast may be used to cast away (remove) constness or volatility.
1) Two possibly multilevel pointers to the same type may be converted between each other, regardless of cv-qualifiers at each level.
I've googled around a bit already and haven't found any concise, straightforward definitions of what a multilevel pointer is. So: what exactly is a multilevel pointer?
(Possible face-palm moment) It it just a pointer to a pointer, or pointer to a pointer to a pointer, e.g. int ** or int ***?
Is it just a pointer to a pointer, or pointer to a pointer to a pointer, e.g. int ** or int ***?
It is exactly this, yes.
Take this for example:
const Integer operator+(const Integer& left, const Integer& right) {
return Integer(left.i + right.i);
}
(taken from page 496 of Thinking in C++)
What is the part after the return statement? A cast (to make the result of the sum an Integer) or a call to the constructor of the class Integer? Or maybe something else that I ignore..
This is the constructor:
Integer(long ll = 0) : i(ll) {}
Edit:
i it's long int.
Casting means "changing an entity of one data type into another". That said, you can consider Integer() as a cast from long to Integer, as the two types are related and the operation translates into "build an object of type B, starting with an object of type A".
With this syntax, there is no protection against misuse, i.e. if the constructor takes only one parameter, the parameter might not be used to build an object directly representing the first (e.g. each QWidget takes a pointer to the parent, but it is not representing its parent, obviously), and you cannot do anything to prevent this. You could block implicit initialization by marking single-parameter constructor as explicit, but nothing more.
The syntax for old-style casts and constructors with only one parameter is exactly the same, and that's the reason why a new syntax was created for the first: use new style (explicit) C++ syntax for casts, that is, const_cast, dynamic_cast, static_cast or reinterpret_cast as appropriate.
In the very words of Bjarne Stroustrup, this verbose casting syntax was introduced to make clear when a cast is taking place. Note that having four forms also allows for proper differentiation of the programmer's intent.
Finally, int() and such are considered old-style for plain types (int, long, etc.) and newvar = (T)oldvar form exists only because of C compatibility constraint.
Its a constructor call.
Object creation in c++ will be in 2 ways,
Integer* i = new Integer(args); //A Pointer i , pointing to the object created at a memory location.
or
Integer i = Integer(args); //Object i
Your case is 2nd one, but the initialized object is not assigned to i. Rather it is passed as it is.
Moreover,
A cast could be trivial if it is (DataType) value., In this case it would be surely a cast.
But in the case of DataType(value) if it is a primitive type, it would be a cast, but if it is a non-primitive type surely it will be a constructor call.
I'm trying to implement a C++ class with a value field that can point to anything (a bit like in boost::any). Currently I do the following:
class MyClass {
void* value;
template<typename T>
Myclass(const &T v) {
value = (void*)(new T(v));
}
};
The problem is now to implement a getValue() operation that creates a copy of the inner value with the right type:
template<typename T>
T getValue() {
return *value;
}
Here it cannot work because I'm trying to unreference a void* pointer. I was wondering which cast (static_cast? dynamic_cast? other...) I should use such that *value is properly converted into a T object and an exception is thrown if value was not originally of this type?
Thanks
You cannot dereference a void*, it simply makes no sense. Why not make the class itself generic? Then you can have:
template<typename T>
class MyClass {
T* value;
MyClass(const T& v) {
value = new T(v);
}
T getValue() {
return *value;
}
};
Make sure to create a destructor which deallocates value and also to follow The Rule of Three. You could also make a version of getValue that returns a const T& (const reference to T) to avoid the copy if one is not required.
which cast (static_cast? dynamic_cast? other...) I should use such that *value is properly converted into a T object
If you must do this conversion, then you should use static_cast, which in general is designed to (among other things) reverse any standard conversion. There's a standard conversion from any object pointer type to void*, and your getter reverses it, so use the cast designed for that:
return *static_cast<T*>(value);
You should also either remove the C-style cast from your constructor, or replace that with a static_cast too.
A reinterpret_cast would also work, but is "overkill". In general you should use the cast that is as restrictive as possible while still performing the conversion you need.
and an exception is thrown if value was not originally of this type
You are out of luck there - C++ cannot in general tell what the original type of the object was, once you've cast the pointer to void*. Your code relies on the caller to call getValue with the correct type. For example, consider what happens if the original type was char -- that's just one byte in C++, there is no room set aside for any type information that would allow the compiler to check the cast in getValue.
dynamic_cast does check types in some limited circumstances, but since your template is fully generic, those limited circumstances might not apply.
If you don't like this, you could change your class to store, in addition to the object pointer, a pointer to a type_info object (resulting from a use of the typeid operator). See the standard header <typeinfo>. You could then compare the type_info object for the type T in the constructor, with the type_info object for the type T in getValue, and throw if they don't match.
As you say, your class is intended to be a bit like boost::any, and getValue is like any_cast. You could consult the source and documentation of that class to see the tricks needed to do what you want. If there were a straightforward way to do it, then boost::any would be a straightforward class!
You can't. C++ doesn't provide that sort of mechanism, at least not directly, not for void*. A void* does not have any information that the computer would need to determine what it is, and attempting to "check" if it is a valid whatever-you-cast-it-to is impossible because there aren't particular flags for that.
There are options, though. The first is to use some kind of universal base class, similar to Java's Object, and derive all of your other classes from that. dynamic_cast will now work the way you want (returning NULL if the object is not a valid object of the class you casted it to).
Another is to simply keep track of what type of object it is yourself. That means augmenting the void* with another value that tells you what you need to cast it to.
But really, neither of these things strike me as good ideas. I think there is almost-definitely some other aspect of your design that should be changed rather than using these. Using templates, as #EdS. suggests, is a very good option, for example.