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.
Related
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.
I have two versions of the same static member function: one takes a pointer-to-const parameter and that takes a pointer-to-non-const parameter. I want to avoid code duplication.
After reading some stack overflow questions (these were all about non-static member functions though) I came up with this:
class C {
private:
static const type* func(const type* x) {
//long code
}
static type* func(type* x) {
return const_cast<type*>(func(static_cast<const type*>(x)));
}
public:
//some code that uses these functions
};
(I know juggling with pointers is generally a bad idea, but I'm implementing a data structure.)
I found some code in libstdc++ that looks like this:
NOTE: these are not member functions
static type* local_func(type* x)
{
//long code
}
type* func(type* x)
{
return local_func(x);
}
const type* func(const type* x)
{
return local_func(const_cast<type*>(x));
}
In the first approach the code is in a function that takes a pointer-to-const parameter.
In the second approach the code is in a function that takes a pointer-to-non-const parameter.
Which approach should generally be used? Are both correct?
The most important rule is that an interface function (public method, a free function other than one in a detail namespace, etc), should not cast away the constness of its input. Scott Meyer was one of the first to talk about preventing duplication using const_cast, here's a typical example (How do I remove code duplication between similar const and non-const member functions?):
struct C {
const char & get() const {
return c;
}
char & get() {
return const_cast<char &>(static_cast<const C &>(*this).get());
}
char c;
};
This refers to instance methods rather than static/free functions, but the principle is the same. You notice that the non-const version adds const to call the other method (for an instance method, the this pointer is the input). It then casts away constness at the end; this is safe because it knows the original input was not const.
Implementing this the other way around would be extremely dangerous. If you cast away constness of a function parameter you receive, you are taking a big risk in UB if the object passed to you is actually const. Namely, if you call any methods that actually mutate the object (which is very easy to do by accident now that you've cast away constness), you can easily get UB:
C++ standard, section § 5.2.11/7 [const cast]
[ Note: Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a
const_cast that casts away a const-qualifier may produce undefined
behavior. —end note ]
It's not as bad in private methods/implementation functions because perhaps you carefully control how/when its called, but why do it this way? It's more dangerous to no benefit.
Conceptually, it's often the case that when you have a const and non-const version of the same function, you are just passing along internal references of the object (vector::operator[] is a canonical example), and not actually mutating anything, which means that it will be safe either way you write it. But it's still more dangerous to cast away the constness of the input; although you might be unlikely to mess it up yourself, imagine a team setting where you write it the wrong way around and it works fine, and then someone changes the implementation to mutate something, giving you UB.
In summary, in many cases it may not make a practical difference, but there is a correct way to do it that's strictly better than the alternative: add constness to the input, and remove constness from the output.
I have actually only ever seen your first version before, so from my experience it is the more common idiom.
The first version seems correct to me while the second version can result in undefined behavior if (A) you pass an actual const object to the function and (B) the long code writes to that object. Given that in the first case the compiler will tell you if you're trying to write to the object I would never recommend option 2 as it is. You could consider a standalone function that takes/returns const however.
Think in a similar fashion like:
1. The bare name of an array is equivalent with the pointer to the first element, without the need to specify index 0.
2. toString() from Java makes it possible to use the name of an object as a string without calling any object method.
Now is there a way in C++ to use the name of a class object to refer to its first member?
Consider:
class Program
{
public:
int id;
char *str;
};
void function(int p)
{
//...
}
and then:
Program prog0;
function(prog0); // instead of function(prog0.id)
Any way to "hide" the member reference?
EDIT:
Why was the holyBlackCat's answer deleted? I was inclining to vote it as the best answer -- no offense, Mateusz. But he was the first to suggest conversion operator and the example was complete and simple.
In C++, such behaviour would be a cataclysm. If I understand correctly, Java tries to convert object of type A to object of type B by searching for first member in A, that is of type B or is implicitly convertible to B.
C++ wasn't designed that way. We like to write code, that is always predictable. You can achieve what you want, but for a price.
The best solution in this case would be conversion operator - consider:
class Program
{
public:
int id;
char *str;
operator int()
{
return this->id;
}
//You can have more than one!
operator const char*()
{
return this->str;
}
};
void function_int(int p)
{
}
void function_str(const char* s)
{
}
Now it is possible to do the following:
Program prog;
function_int(prog); //Equivalent of function_int(prog.id)
function_str(prog); //Equivalent of function_int(prog.str)
The price is, that if you add another int and place it before id it will not be used in conversion, because we stated in our operator explicitly, that "int content" of our class is represented by id and this member is considered when it comes to such conversion.
However, even this simple example shows some potential problems - overloading functions with integral and pointer types could result in very unpredictable behavior. When type contains conversion operators to both pointers and integers, it can get even worse.
Assume, that we have following function:
void func(unsigned long)
{
}
And we call func with argument of type Program. Which conversion operator would you expect to be called? Compiler knows how to convert Program to either int or const char*, but not unsigned long. This article on cppreference should help you to understand how implicit conversions work.
Also, as Barry pointed out, more meaningless constructs become available. Consider this one:
int x = prog + 2
What does it mean? It is perfectly valid code, though. That is why conversion operators should be dosed extremely carefully (in pre-C++11 era, there was a general advise, that every class should have at most one such operator).
Quote from MSDN:
If a conversion is required that causes an ambiguity, an error is generated. Ambiguities arise when more than one user-defined conversion is available or when a user-defined conversion and a built-in conversion exist.
Sometimes, simple solution to this problem is to mark conversion operator with explicit keyword, so you would need to change above calls to:
function_int((int)prog);
function_str((const char*)prog);
It is not as pretty as the previous form, but much safer. It basically means, that compiler is forbidden to perform any implicit conversion using operator marked as explicit. Very useful to avoid ambiguous calls, while still providing some flexibility in code - you can still very easily convert objects of one type to another, but you can be sure when and where these conversions are performed.
However, explicit conversion operators are still not supported by some compilers, as this is C++ 11 feature (for example, Visual C++ 11 doesn't support it).
You can read more about explicit keyword here.
Now is there a way in C++ to use the name of a class object to refer to its first member?
No, C++ doesn't have any reflection, so there's no way to actually determine what the "first member" is.
However, if what you really want is to get an ID for any object, you could just require that object to have that method:
template <typename T>
void function(const T& t) {
int id = t.getID();
// etc.
}
Without knowing more about your use-case, it's hard to know what to propose.
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.
In my program, I have objects (of the same class) that must all have a unique identifier. For simplicity and performance, I chose to use the address of the object as identifier. And to keep the types simple, I use (void*) as a type for this identifier. In the end I have code like this:
class MyClass {
public:
typedef void* identity_t;
identity_t id() const { return (void*)this; }
}
This seems to be working fine, but gcc gives me a strict-aliasing warning. I understand the code would be bad if the id was used for data transfer. Luckily it is not, but the question remains: will aliasing optimisations have an impact on the code produced? And how to avoid the warning?
Note: I am reluctant to use (char*) as this would imply the user can use the data for copy, which it can not!
You could try using the type uintptr_t instead of void*. uintptr_t is a integer type that is defined as being big enough to hold any pointer value. And since it's not actually a pointer, the compiler won't flag any aliasing problems.
class MyClass {
public:
typedef uintptr_t identity_t;
identity_t id() const { return (identity_t)this; }
}
You are violating logical constness returning the object as mutable in a const method.
As Neil points out, no cast is needed.
class MyClass {
public:
typedef const void* identity_t;
identity_t id() const { return this; }
};
Try using
return static_cast<void*>(this);
This should be perfectly safe, any pointer should be able to be cast to void * without risk of loss.
I originally suggested dynamic_cast(this);, but after reading up a bit I think it adds no advantage, and since it's RTTI-only it's not a good solution in general.
By the way, I would make the returned value const, since the identity of an object cannot change.
I can't see any aliasing issues. However, you are casting away constness (since the id function is const), which the compiler might be unhappy about. Perhaps it'd be better to use const void* as your ID type.
Alternatively, cast the address to an integer type such as size_t. Then it is no longer a pointer, and aliasing becomes a non-issue.
Why not using type MyClass *?
Or type intptr_t?