In C, one can assign a data pointer to a void pointer and then cast it back to the original type, that data pointer will be recovered. The language standard guarantees that such transformation does not lose information. This often means (not necessarily, but true for most platforms) that the size of void pointer is the same with that of data pointers. Thus one can count on these facts to use void pointers as general pointers to heterogeneous types while void pointers themselves are of uniform size and representation. For example, one has an array of void pointers, with its elements pointing to dynamically allocated objects of different types. Constructing such an array makes certain things convenient. My question is: How does one implement something similar, a general pointer type in C++, which comply with the following: (assume g_pointer is the class name )
Constructed from any pointer types, one can write code like
g_pointer g_ptr = g_pointer(new T())Recover the original pointer
T* ptr = g_ptr.recover(), or auto* ptr = g_tr.recover()Update: According to some comments, the above couldn't be done in C++, then something like
recover<Type>(g_ptr)should suffice, throwing an exception Type is not compatible.
g_pointer can be contained in std::vector or a plain array, that is basically means
sizeof(g_pointer) // a predetermined constant number,(Update: This is always true, provided such a class can be correctly implemented, thanks for pointing out.)
I have just found boost::any, a peek into its introduction seems suggeesting that it may be what I want, although it might not be the case. So anyone who is familiar with boost::any is welcomed to comment.
Update: (response to some comments)
- A g_pointer type object should be aware of the underlying type of the object to which it points. thus the recover method should always return a pointer of that type.
- A general pointer type, meaning a reference to ANY object, IMHO, is a reasonable thing to ask to any language supporting object-oriented paradigm.
Update: Thanks @Caleth, std::any is great.
It is impossible in C++. Because the type of the expression
g_ptr.recover()is determined at compile time, it cannot store information of the underlying type, which is determined at runtime.If you can tolerate expressions like
g_ptr.recover<T>(), you can implementg_pointerby wrapping avoid*and aconst std::type_info&that stores the information of the actual type the pointer points to, e.g.Note this
g_pointerbehaves like a raw pointer rather than a smart pointer, which means it does not own the object it points to.There is still a defect in the implementation above:
const T*cannot be implicitly converted tovoid*, thus the general pointer cannot holdconst T*. To handle const-qualifiers, you can change the type of_datatoconst void*and useconst_castwhen recovering. In addition,recovershall reject to return a pointer to non-const object from ag_pointerholding a pointer to const object. However,typeidoperator ignores top const-qualifiers, so we need an additional data member to record whether the pointer points to an originally const object.