Class identity without RTTI - c++

I've found a simple solution somewhere on the internet to an identity class without built-in C++ RTTI.
template <typename T>
class Identity {
public:
static int64_t id()
{
static int64_t dummy;
return reinterpret_cast<int64_t>(&dummy);
}
};
When we need some class ID, we just use:
Identity<OurClass>::id();
I'm wondering, are there any collisions? Can it return the same ID for the different classes, or the different ID for the same classes? I have tried this code with g++ with different optimization values, everything seems ok.

First off: there is such an integral type that is made specifically to contain pointers:
intptr_t
and in C++11 uintptr_t
Second, even though in practice on gcc they are equal, the size of a pointer to an object and the size of a function pointer (or pointer to member) might well be different. Therefore it would be better using a specific object rather than the method itself (for Standard conformance).
Third, it only gives you identity, while RTTI is much richer, as it knows about all the subclasses a given object can be cast to, and even allows cross-casts or casts across virtual inheritance.
Still, the corrected version can be useful I guess:
struct Foo {
static intptr_t Id() {
static boost::none_t const Dummy = {};
return reinterpret_cast<intptr_t>(&Dummy);
}
};
And in hierarchies, having a virtual function returning that ID.
For completeness, I'll mention that Clang and LLVM have their own way of dealing with object identification without RTTI. You may want to read about their way of implementing isa, cast and dyn_cast here.

This solution casts a function pointer to an int. There is no guarantee that this pointer fits into an int, although in practice sizeof(void *) == sizeof(void (*)()) <= sizeof(int)
Edit: My bad. On x86_64 sizeof(int) = 4, sizeof(void (*)()) = 8, so collisions are possible and are unpredictable.
You can cast to an integral of appropriate size, but still it is undefined behavior theoretically.

This version avoids undefined behavior (and compiler warnings):
template <typename T>
class Identity {
public:
static const int* id() { static const int id = 0; return &id; }
};

Related

std::any without RTTI, how does it work?

If I want to use std::any I can use it with RTTI switched off. The following example compiles and runs as expected also with -fno-rtti with gcc.
int main()
{
std::any x;
x=9.9;
std::cout << std::any_cast<double>(x) << std::endl;
}
But how std::any stores the type information? As I see, if I call std::any_cast with the "wrong" type I got std::bad_any_cast exception as expected.
How is that realized or is this maybe only a gcc feature?
I found that boost::any did also not need RTTI, but I found also not how that is solved. Does boost::any need RTTI?.
Digging into the STL header itself gives me no answer. That code is nearly unreadable to me.
TL;DR; std::any holds a pointer to a static member function of a templated class. This function can perform many operations and is specific to a given type since the actual instance of the function depends on the template arguments of the class.
The implementation of std::any in libstdc++ is not that complex, you can have a look at it:
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/any
Basically, std::any holds two things:
A pointer to a (dynamically) allocated storage;
A pointer to a "storage manager function":
void (*_M_manager)(_Op, const any*, _Arg*);
When you construct or assign a new std::any with an object of type T, _M_manager points to a function specific to the type T (which is actually a static member function of class specific to T):
template <typename _ValueType,
typename _Tp = _Decay<_ValueType>,
typename _Mgr = _Manager<_Tp>, // <-- Class specific to T.
__any_constructible_t<_Tp, _ValueType&&> = true,
enable_if_t<!__is_in_place_type<_Tp>::value, bool> = true>
any(_ValueType&& __value)
: _M_manager(&_Mgr::_S_manage) { /* ... */ }
Since this function is specific to a given type, you don't need RTTI to perform the operations required by std::any.
Furthermore, it is easy to check that you are casting to the right type within std::any_cast. Here is the core of the gcc implementation of std::any_cast:
template<typename _Tp>
void* __any_caster(const any* __any) {
if constexpr (is_copy_constructible_v<decay_t<_Tp>>) {
if (__any->_M_manager == &any::_Manager<decay_t<_Tp>>::_S_manage) {
any::_Arg __arg;
__any->_M_manager(any::_Op_access, __any, &__arg);
return __arg._M_obj;
}
}
return nullptr;
}
You can see that it is simply an equality check between the stored function inside the object you are trying to cast (_any->_M_manager) and the manager function of the type you want to cast to (&any::_Manager<decay_t<_Tp>>::_S_manage).
The class _Manager<_Tp> is actually an alias to either _Manager_internal<_Tp> or _Manager_external<_Tp> depending on _Tp.
This class is also used for allocation / construction of object for the std::any class.
Manual implementation of a limited RTTI is not that hard. You're gonna need static generic functions. That much I can say without providing a complete implementation.
here is one possibility:
class meta{
static auto id(){
static std::atomic<std::size_t> nextid{};
return ++nextid;//globally unique
};
std::size_t mid=0;//per instance type id
public:
template<typename T>
meta(T&&){
static const std::size_t tid{id()};//classwide unique
mid=tid;
};
meta(meta const&)=default;
meta(meta&&)=default;
meta():mid{}{};
template<typename T>
auto is_a(T&& obj){return mid==meta{obj}.mid;};
};
This is my first observation; far from ideal, missing many details. One may use one instance of meta as a none-static data member of his supposed implementation of std::any.
One of possible solutions is generating unique id for every type possibly stored in any (I assume You know moreless how any internally works). The code that can do it may look something like this:
struct id_gen{
static int &i(){
static int i = 0;
return i;
}
template<class T>
struct gen{
static int id() {
static int id = i()++;
return id;
}
};
};
With this implemented You can use the id of the type instead of RTTI typeinfo to quickly check the type.
Notice the usage of static variables inside functions and static functions. This is done to avoid the problem of undefined order of static variable initialization.

Placement new based on template sizeof()

Is this legal in c++11? Compiles with the latest intel compiler and appears to work, but I just get that feeling that it is a fluke.
class cbase
{
virtual void call();
};
template<typename T> class functor : public cbase
{
public:
functor(T* obj, void (T::*pfunc)())
: _obj(obj), _pfunc(pfunc) {}
virtual void call()
{
(_obj)(*_pfunc)();
}
private:
T& _obj;
void (T::*_pfunc)();
//edited: this is no good:
//const static int size = sizeof(_obj) + sizeof(_pfunc);
};
class signal
{
public:
template<typename T> void connect(T& obj, void (T::*pfunc)())
{
_ptr = new (space) functor<T>(obj, pfunc);
}
private:
cbase* _ptr;
class _generic_object {};
typename aligned_storage<sizeof(functor<_generic_object>),
alignment_of<functor<_generic_object>>::value>::type space;
//edited: this is no good:
//void* space[(c1<_generic_object>::size / sizeof(void*))];
};
Specifically I'm wondering if void* space[(c1<_generic_object>::size / sizeof(void*))]; is really going to give the correct size for c1's member objects (_obj and _pfunc). (It isn't).
EDIT:
So after some more research it would seem that the following would be (more?) correct:
typename aligned_storage<sizeof(c1<_generic_object>),
alignment_of<c1<_generic_object>>::value>::type space;
However upon inspecting the generated assembly, using placement new with this space seems to inhibit the compiler from optimizing away the call to 'new' (which seemed to happen while using just regular '_ptr = new c1;'
EDIT2: Changed the code to make intentions a little clearer.
const static int size = sizeof(_obj) + sizeof(_pfunc); will give the sum of the sizes of the members, but that may not be the same as the size of the class containing those members. The compiler is free to insert padding between members or after the last member. As such, adding together the sizes of the members approximates the smallest that object could possibly be, but doesn't necessarily give the size of an object with those members.
In fact, the size of an object can vary depending not only on the types of its members, but also on their order. For example:
struct A {
int a;
char b;
};
vs:
struct B {
char b;
int a;
};
In many cases, A will be smaller than B. In A, there will typically be no padding between a and b, but in B, there will often be some padding (e.g., with a 4-byte int, there will often be 3 bytes of padding between b and a).
As such, your space may not contain enough...space to hold the object you're trying to create there in init.
I think you just got lucky; Jerry's answer points out that there may be padding issues. What I think you have is a non-virtual class (i.e., no vtable), with essentially two pointers (under the hood).
That aside, the arithmetic: (c1<_generic_object>::size / sizeof(void*)) is flawed because it will truncate if size is not a multiple of sizeof(void *). You would need something like:
((c1<_generic_object>::size + sizeof(void *) - 1) / sizeof(void *))
This code does not even get to padding issues, because it has a few of more immediate ones.
Template class c1 is defined to contain a member T &_obj of reference type. Applying sizeof to _obj in scope of c1 will evaluate to the size of T, not to the size of reference member itself. It is not possible to obtain the physical size of a reference in C++ (at least directly). Meanwhile, any actual object of type c1<T> will physically contain a reference to T, which is typically implemented in such cases as a pointer "under the hood".
For this reason it is completely unclear to me why the value of c1<_generic_object>::size is used as a measure of memory required for in-pace construction of an actual object of type c1<T> (for any T). It just doesn't make any sense. These sizes are not related at all.
By pure luck the size of an empty class _generic_object might evaluate to the same (or greater) value as the size of a physical implementation of a reference member. In that case the code will allocate a sufficient amount of memory. One might even claim that the sizeof(_generic_object) == sizeof(void *) equality will "usually" hold in practice. But that would be just a completely arbitrary coincidence with no meaningful basis whatsoever.
This even looks like red herring deliberately inserted into the code for the purpose of pure obfuscation.
P.S. In GCC sizeof of an empty class actually evaluates to 1, not to any "aligned" size. Which means that the above technique is guaranteed to initialize c1<_generic_object>::size with a value that is too small. More specifically, in 32 bit GCC the value of c1<_generic_object>::size will be 9, while the actual size of any c1<some_type_t> will be 12 bytes.

provide member pointer to the member itself

I am implementing my C#-like property class in C++.
So I have to provide acceess to the internal field(mother::_i) to the property field(mother::i).
I found few solutions but there were no perfects.
Firstly I made a method to provide owner(mother in this case)'s pointer on runtime by calling method like RProperty<...>::SetOwner(mother&). But it requires additional code to use my property class and costs in runtime.
Secondly I came up with idea that this pointer of RProperty and member pointer of itself can find the owner's pointer. obviously, ownerpointer = this - &mother::i. But providing member pointer to member itself gives me compile time error. I tried a tricky method using 'empty' struct to provide member pointer to property. But it turns out sizeof(struct empty) is not zero. it costs unnecessary extra memory per instances. I stucked in this issue for few days.
anyone has a good idea? :)
Code works but not perfect:
#include "stdafx.h"
struct empty{};
template<typename TCLASS, typename TFIELD>
class RPropertyBase
{
protected:
RPropertyBase(){ }
TCLASS& getOwner() const { };
};
template<typename TCLASS, typename TFIELD, TFIELD TCLASS::*PFIELD, empty TCLASS::*PTHIS>
class RProperty : RPropertyBase<TCLASS, TFIELD>
{
protected:
TCLASS& getOwner() const { return *(TCLASS*)((unsigned int)this-(unsigned int)&(((TCLASS*)0)->*PTHIS)-sizeof(empty) ); }
public:
RProperty<TCLASS, TFIELD, PFIELD, PTHIS>& operator=(const TFIELD& A){ getOwner().*PFIELD = A; return *this; }
operator TFIELD&() const { return getOwner().*PFIELD; }
};
class mother
{
int _i;
template<typename C>
struct __Propertyi : public RProperty<C, int, &C::_i, &C::_empty>
{
using RProperty<C, int, &C::_i, &C::_empty>::operator=;
};
public:
empty _empty;
__Propertyi<mother> i;
};
int _tmain(int argc, _TCHAR* argv[])
{
mother a;
a.i = 1;
int bb = (a.i);
return 0;
}
First...
So I have to provide acceess to the internal field(mother::_i) to the property field(mother::i).
Identifiers beginning with an underscore are reserved in C++ - only the compiler and it's libraries are supposed to use them. Identifiers containing double-underscores are also reserved. However, identifiers with a single trailing underscore such as i_ are OK.
Getting to the point...
ownerpointer = this - &mother::i
It looks like you're trying to subtract a member pointer from a pointer, which you can't do. Member pointers are a bit like offsets into the layout of a type, but this breaks down in two ways...
It's not the abstraction they're designed to provide.
It's not accurate anyway - once you allow for multiple inheritance and virtual inheritance, the offset at which a particular member appears within a type doesn't just depend on it's position within the base type in which it's defined, but also on which subtype you're looking at.
If you really want to do pointer arithmetic that's aware of the layout of a type, it's certainly possible, but it's a C programming technique that uses C-level features. There's also some significant limitations on context.
The key idea is that instead of trying to use member pointers as offsets, you use actual offsets. This costs you type-safety but, so long as you wrap the type-unsafe code and make absolutely certain it's correct, you should be OK.
The basic tool is offsetof, which is a macro that C++ inherits from C...
offsetof(structname, membername)
You can look up the implementation of that macro, but don't copy it - the standard requires that a compiler provide some way to implement the macro that works, but the implementation that works for one compiler may not work for another. However, two common approaches are...
Look at the address of the member in an imaginary instance of the struct at address zero. Problems with this (e.g. that imaginary instance obviously doesn't have a valid virtual pointer) are part of the reason for some restrictions.
Use a special "intrinsic" function provided by the compiler, which is one of the reasons why those identifiers with underscores are reserved.
Using that offset, in principle, you can cast your pointer to char* via void*, do your arithmetic, then cast back again to the needed type.
The first problem is obvious - some members (ie the static ones) aren't at a fixed offset in each instance, they're at a fixed address irrespective of the instance. Obvious but perhaps best to say it.
The next problem is from that offsetof documentation I linked...
type shall be a POD class (including unions).
You're looking at the layout of a type. You need that layout to apply to subtypes as well. Because you've discarded the C++ polymorphism abstraction and you're dealing directly with offsets, the compiler can't handle any run-time layout resolution for you. Various inheritance-related issues would invalidate the offset calculations - multiple inheritance, virtual inheritance, a subtype that has a virtual pointer when the base doesn't.
So you need to do your layout with a POD struct. You can get away with single inheritance, but you can't have virtual methods. But there's another annoyance - POD is a bit of an overloaded term that obviously doesn't just relate to whether offsetof is valid or not. A type that has non-POD data members isn't POD.
I hit this problem with a multiway tree data structure. I used offsetof to implement the data structure (because different times). I wrapped this in a template, which used a struct and offsetof to determine the node layouts. In a whole series of compilers and compiler versions this was fine until I switched to a version of GCC, which started warning all over the place.
My question and answer about this on SO are here.
This issue with offsetof may have been addressed in C++11 - I'm not sure. In any case, even though a member within a struct is non-POD, that struct will still have a fixed layout determined at compile time. The offset is OK even if the compiler throws warnings at you, which luckily in GCC can be turned off.
The next problem from that offsetof documentation I linked...
type shall be a standard-layout class (including unions).
This is a new one from C++11 and, to be honest, I haven't really thought about it much myself.
The final problem - actually, the view of a pointer as an address is invalid. Sure, the compiler implements pointers as addresses, but there's lots of technicalities, and compiler writers have been exploiting these in their optimisers.
One area you have to be very careful with once you start doing pointer arithmetic is the compilers "alias analysis" - how it decides whether two pointers might point to the same thing (in order to decide when it can safely keep values in registers and not refer back to memory to see if a write through an alias pointer changed it). I once asked this question about that, but it turns out the answer I accepted is a problem (I should probably go back and do something about it) because although it describes the problem correctly, the solution it suggests (using union-based puns) is only correct for GCC and not guaranteed by the C++ standard.
In the end, my solution was to hide the pointer arithmetic (and char* pointers) in a set of functions...
inline void* Ptr_Add (void* p1, std::ptrdiff_t p2)
{
return (((char*) p1) + p2);
}
inline void* Ptr_Sub (void* p1, std::ptrdiff_t p2)
{
return (((char*) p1) - p2);
}
inline std::ptrdiff_t Ptr_Diff (void* p1, void* p2)
{
return (((char*) p1) - ((char*) p2));
}
inline bool Ptr_EQ (void* p1, void* p2) { return (((char*) p1) == ((char*) p2)); }
inline bool Ptr_NE (void* p1, void* p2) { return (((char*) p1) != ((char*) p2)); }
inline bool Ptr_GT (void* p1, void* p2) { return (((char*) p1) > ((char*) p2)); }
inline bool Ptr_GE (void* p1, void* p2) { return (((char*) p1) >= ((char*) p2)); }
inline bool Ptr_LT (void* p1, void* p2) { return (((char*) p1) < ((char*) p2)); }
inline bool Ptr_LE (void* p1, void* p2) { return (((char*) p1) <= ((char*) p2)); }
That std::ptrdiff_t type is significant too - the bit-width of a pointer isn't guaranteed to match the bit-width of a long.
Outside of these functions, all pointers are either their correct type or void*. C++ treats void* specially (the compiler knows it can alias other pointer types) so it seems to work, though there may be details I'm not remembering. Sorry - these things are hard, especially these days with optimisers that are sometimes clever in the "obnoxious pedant" sense, and I only touch this evil code if I absolutely have to.
One last issue - I already mentioned that pointers aren't addresses. One oddity is that on some platforms, two different pointers may map to the same address in different address spaces - see for example the Harvard Architecture which has different address spaces for instructions. So even the offset between two pointers is invalid except within certain limits, no doubt described in complicated detail in the standard. A single struct is a single struct - obviously it lives on one address space, with the possible exception of static members - but don't just assume pointer arithmetic is always valid.
Long story short - yes, it's possible to subtract the offset of a member from the address of a member to find the address of the struct, but you have to use actual offsets (not member pointers) and there are limitations and technicalities that may mean you can't even solve your problem this way (e.g. I'm not sure you'll be able to use offsets as template parameters), and certainly mean it's harder than it seems.
Ultimately, the take-away advice is that if you read this, treat it as a warning. Don't do the things I've done. I wish I hadn't, and probably so will you.

Using RTTI to determine inheritance graph in C++?

What, if any, c++ constructs are there for listing the ancestors of a class at runtime?
Basically, I have a class which stores a pointer to any object, including possibly a primitive type (somewhat like boost::any, which I don't want to use because I need to retain ownership of my objects). Internally, this pointer is a void*, but the goal of this class is to wrap the void* with runtime type-safety. The assignment operator is templated, so at assignment time I take the typeid() of the incoming pointer and store it. Then when I cast back later, I can check the typeid() of the cast type against the stored type_info. If it mismatches, the cast will throw an exception.
But there's a problem: It seems I lose polymorphism. Let's say B is a base of D. If I store a pointer to D in my class, then the stored type_info will also be of D. Then later on, I might want to retrieve a B pointer. If I use my class's method to cast to B*, then typeid(B) == typeid(D) fails, and the cast raises an exception, even though D->B conversion is safe. Dynamic_cast<>() doesn't apply here, since I'm operating on a void* and not an ancestor of B or D.
What I would like to be able to do is check is_ancestor(typeid(B), typeid(D)). Is this possible? (And isn't this what dynamic_cast<> is doing behind the scenes?)
If not, then I am thinking of taking a second approach anyway: implement a a class TypeInfo, whose derived classes are templated singletons. I can then store whatever information I like in these classes, and then keep pointers to them in my AnyPointer class. This would allow me to generate/store the ancestor information at compile time in a more accessible way. So failing option #1 (a built-in way of listing ancestors given only information available at runtime), is there a construct/procedure I can use which will allow the ancestor information to be generated and stored automatically at compile-time, preferably without having to explicitly input that "class A derives from B and C; C derives from D" etc.? Once I have this, is there a safe way to actually perform that cast?
I had a similar problem which I solved through exceptions! I wrote an article about that:
Part 1, Part 2 and code
Ok. Following Peter's advise the outline of the idea follows. It relies on the fact that if D derives from B and a pointer to D is thrown, then a catch clause expecting a pointer to B will be activated.
One can then write a class (in my article I've called it any_ptr) whose template constructor accepts a T* and stores a copy of it as a void*. The class implements a mechanism that statically cast the void* to its original type T* and throws the result. A catch clause expecting U* where U = T or U is a base of T will be activated and this strategy is the key to implementing a test as in the original question.
EDIT: (by Matthieu M. for answers are best self-contained, please refer to Dr Dobbs for the full answer)
class any_ptr {
void* ptr_;
void (*thr_)(void*);
template <typename T>
static void thrower(void* ptr) { throw static_cast<T*>(ptr); }
public:
template <typename T>
any_ptr(T* ptr) : ptr_(ptr), thr_(&thrower<T>) {}
template <typename U>
U* cast() const {
try { thr_(ptr_); }
catch (U* ptr) { return ptr; }
catch (...) {}
return 0;
}
};
The information is (often) there within the implementation. There's no standard C++ way to access it though, it's not exposed. If you're willing to tie yourself to specific implementations or sets of implementations you can play a dirty game to find the information still.
An example for gcc, using the Itanium ABI is:
#include <cassert>
#include <typeinfo>
#include <cxxabi.h>
#include <iostream>
bool is_ancestor(const std::type_info& a, const std::type_info& b);
namespace {
bool walk_tree(const __cxxabiv1::__si_class_type_info *si, const std::type_info& a) {
return si->__base_type == &a ? true : is_ancestor(a, *si->__base_type);
}
bool walk_tree(const __cxxabiv1::__vmi_class_type_info *mi, const std::type_info& a) {
for (unsigned int i = 0; i < mi->__base_count; ++i) {
if (is_ancestor(a, *mi->__base_info[i].__base_type))
return true;
}
return false;
}
}
bool is_ancestor(const std::type_info& a, const std::type_info& b) {
if (a==b)
return true;
const __cxxabiv1::__si_class_type_info *si = dynamic_cast<const __cxxabiv1::__si_class_type_info*>(&b);
if (si)
return walk_tree(si, a);
const __cxxabiv1::__vmi_class_type_info *mi = dynamic_cast<const __cxxabiv1::__vmi_class_type_info*>(&b);
if (mi)
return walk_tree(mi, a);
return false;
}
struct foo {};
struct bar : foo {};
struct baz {};
struct crazy : virtual foo, virtual bar, virtual baz {};
int main() {
std::cout << is_ancestor(typeid(foo), typeid(bar)) << "\n";
std::cout << is_ancestor(typeid(foo), typeid(baz)) << "\n";
std::cout << is_ancestor(typeid(foo), typeid(int)) << "\n";
std::cout << is_ancestor(typeid(foo), typeid(crazy)) << "\n";
}
Where I cast the type_info to the real type that's used internally and then recursively used that to walk the inheritance tree.
I wouldn't recommend doing this in real code, but as an exercise in implementation details it's not impossible.
First, what you are asking for cannot be implemented just on top of type_info.
In C++, for a cast to occur from one object to another, you need more than blindly assuming a type can be used as another, you also need to adjust the pointer, because of multi-inheritance (compile-time offset) and virtual inheritance (runtime offset).
The only way to safely cast a value from a type into another, is to use static_cast (works for single or multi-inheritance) and dynamic_cast (also works for virtual inheritance and actually checks the runtime values).
Unfortunately, this is actually incompatible with type erasure (the old template-virtual incompatibility).
If you limit yourself to non-virtual inheritance, I think it should be possible to achieve this by storing the offsets of conversions to various bases in some Configuration data (the singletons you are talking about).
For virtual inheritance, I can only think of a map of pairs of type_info to a void* (*caster)(void*).
And all this requires enumerating the possible casts manually :(
It is not possible using std::type_info since it does not provide a way to query inheritance information or to convert a std::type_info object to its corresponding type so that you could do the cast.
If you do have a list of all possible types you need to store in your any objects use boost::variant and its visitor.
While I can't think of any way to implement option #1, option #2 should be feasible if you can generate a compile-time list of the classes you would like to use. Filter this type list with boost::MPL and the is_base_of metafunction to get a list of valid-cast typeids, which can be compared to the saved typeid.

Check if a ptr belongs to a virtual class?

My code was acting wonky and i was able to mini reproduce it with the code below. (codepad link)
From http://www.cppreference.com/wiki/keywords/dynamic_cast
If you attempt to cast to a pointer
type, and that type is not an actual
type of the argument object, then the
result of the cast will be NULL.
From my understanding this_test should be null. It isnt. How do i check if that dummy ptr is actually a ptr to a dummy object?
#include <ios>
struct Dummy{ virtual void dummyfn(){} };
int main(){
Dummy* this_test = dynamic_cast<Dummy*>((Dummy*)0x123);
//assert(this_test==0);
cout << std::hex << this_test<<endl;
return 0;
}
output:
0x123
Wishful thinking... :)
I believe dynamic_cast only works for downcasts in polymorphic cases, not any cast whatsoever. It's not like the compiler stores type information for every single variable, so it can't do what you're thinking -- I'm pretty sure it's undefined behavior.
The issue is that dynamic_cast expects either:
a null pointer
a valid pointer
Here you can only offer it garbage, so it is useless, and not the cast you want.
If you are getting a void*, then you can use reinterpret_cast (better than a C-cast, because more visible) to cast it into another type:
void* p = 0x123;
Dummy* dummy = reinterpret_cast<Dummy*>(p);
Note: the presence or absence of virtual methods goes unnoticed here
EDIT: if you can modify the objects being passed...
Then try to use a common base class:
struct Base: private boost::noncopyable { virtual ~Base() = 0 }; Base::~Base() {}
And define the following helpers:
template <typename T>
void* to_void(T* t) {
Base* base = t;
return reinterpret_cast<void*>(base);
}
template <typename T>
T* from_void(void* p) {
Base* base = reinterpret_cast<Base*>(p);
return dynamic_cast<T*>(base);
}
The former is extremely important because of the possible pointer adjustment (which will probably only occur in the case of Multiple Inheritance).
Note: it's possible to use a fast_cast here if you don't use virtual inheritance or other RTTI stuff
template <typename T, typename U>
T* fast_cast(U* u) {
#ifdef NDEBUG
return static_cast<T*>(u);
#else
return dynamic_cast<T*>(u);
#endif
}
If this is not possible the following solutions are possible, but they are going to feel hacky I fear.
Since dynamic_cast is not going to work properly here, you have to actually come up with your own type checking mechanism.
One method could be to use a "repository" in which you register the void* pointers you get, and the associated type_info object.
typedef std::map<void*, std::type_info const*> Repository;
template <typename Dest>
Dest* dynamic_check(void* p, Repository const& rep) {
Repository::const_iterator it = rep.find(p);
assert(it != rep.end() && "dynamic_check: no such entry");
assert(typeid(Dest) == *(it->second) && "dynamic_check: wrong type");
return reinterpret_cast<Dest*>(p);
}
If this is not possible, then you could hack the C++ object model to your advantage. If you know that the object has at least one virtual method, then it necessarily has a virtual pointer on all compilers I know (VS, gcc, clang), and this pointer is the first 4/8 bytes of the object.
inline void* virtual_pointer(void* p) {
assert(p != 0 && "virtual_pointer: null");
return reinterpret_cast<void*>(*p);
}
template <typename T>
void* virtual_pointer(T const& t) {
return virtual_pointer(reinterpret_cast<void*>(&t));
}
template <typename T>
void* virtual_pointer() {
static void* pointer = virtual_pointer(T());
return pointer;
}
template <typename Dest>
Dest* dynamic_check(void* p) {
assert(virtual_pointer<Dest>() == virtual_pointer(p));
return reinterpret_cast<Dest*>(p);
}
Note: both solutions suffer from the same shortcoming, they will only work if you precise the exact type (well, you could get away with it as long as two types share the same virtual table, which happens if a derived class does not override any virtual method, including the destructor).
This is far from the power of a true dynamic_cast.
You skipped one sentence from your quote:
The dynamic_cast keyword casts object from one pointer or reference type to another, performing a runtime check to ensure the validity of the cast.
The problem here is that 0x123 isn't a pointer to an object, so it just doesn't work.
Actually dynamic_cast only works on polymorphic types (usually this means they must have a vtable). Since you're using a C-cast to assert to the compiler that the type is Dummy*, it believes you. Since you're then doing an identity dynamic_cast on a random memory location it doesn't/isn't able to do the type checking.
But seriously, 99% of the time don't try to test that something is a particular type. Design your classes such that the base classes define an interface and the child classes implement it, allowing use without lots of casting (which is a design smell).
dynamic_cast does not perform any run-time checking when you use it for upcasts or identity-casts (casts to the same type). For such casts dynamic_cast behaves exactly the same as an ordinary static_cast. No difference whatsoever.
The page you linked does not mention that, i.e. is not even a remotely complete specification of dynamic_cast, which makes it pretty useless.
C++ provides no means to determine whether a given pointer is actually a valid pointer to a given type. So, you are out of luck there. Implement your own checking method.