I am trying to determine whether an object pointed by a T* pointer is truly a T object, or some other, unrelated type. I tried dynamic_cast, however it is less than useless, it returns the pointer itself instead of null even when it is obvious it does not point to a valid T object:
Object* garbage = reinterpret_cast<Object*>(0x12345678);
if( dynamic_cast<Object*>(garbage) == NULL ){
cout << "Expected behaviour (by me)" << endl;
}else{
cout << "You've got to be kidding me" << endl;
}
Is there any workaround for this, or some other solution? I've tried casting to void* and char* before the dynamic_cast to no avail, typeid is not enough either since I want to accept subclasses as well.
Some context: I'm writing a custom Array class implementing shallow conversion between different kinds of Arrays, like Array<Object*>
and Array<String*>
, and I would like to guarantee a minimal type safety by doing a dynamic type check at every element access, for example:
#define DEBUG
Array<String*> v(10);
Array<Object*> o = v;
o[0] = new Integer(1); // this is technically illegal but no idea how to check
//Array<String*> w = o; // this fails with an exception
String* str = v[0]; // but this should fail horribly as well
cout << str << endl;
Casting to Object*, then doing the type check on the Object* works in a lot of cases, but it fails in the case of Array<Object*>
, though I am not sure whether it is possible to insert something non-Object into an Array<Object*>
without the use of reinterpret_cast.
Base on your example, it sounds like you've got shallow copy Arrays which someone could trick into containing different types than they are supposed to contain. I think the "normal" solution to this problem would be to make that difficult for users to do (i.e. don't provide conversions between Array<T>
and Array<U>
). But, if you're set in your ideas I think this will work:
template<typename Subclass>
class Array {
public:
// ...
Subclass *operator [] (size_t index) {
assert( index < size_ );
assert( dynamic_cast<Subclass*>(static_cast<Object*>(internal_[index])) != NULL );
// ...
}
// ...
private:
size_t size_;
Subclass **internal_;
};
You can do some template meta-magic and a static assert to make sure that Subclass
is really a Subclass of Object
(exactly how is a completely different topic). Once that is out of the way, casting down to an Object* and then back up to Subclass
with a dynamic_cast should accomplish your goal.