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.
Related
I created a vector that stores any type of value (int, bool, string, &, object,...). I can store stuff, but i have no idea how to get an specific element ([index]). EDIT: (without adding the type)
I haven't tried many things because i have no clue. The only tecnic i can think of is dynamic_cast, but since is a template makes no sense.
#include <vector>
#include <iostream>
struct slot {
virtual void print() = 0;
};
template<typename kind>
struct item : public slot {
kind value;
item(kind value) : value{ value } {};
void print()override { std::cout << value<<std::endl; }
};
class Bag {
std::vector<slot*> backpack;
public:
template<typename kind>
void append(kind stuff) {
backpack.push_back(new item<kind>(stuff));
}
void print_to_test() {
for (slot* it : backpack) { it->print(); }
}
//kind get()...How do i get an item value?
};
Bag bag;
bag.append(1);
bag.append(true);
bag.append("Hola");
bag.append(1232131);
void* a = nullptr;
bag.append(a);
bag.print_to_test();
//works fine, prints everything
//but can't get an specific value, like bag[index]
The dynamic cast will work. Note that it requires at least one virtual method - a destructor can be used if nothing else.
Yes, there isn't a way how can you reliably retrieve the value. C++ doesn't have a general object base as other languages nor any useful runtime reflection.
What you've implemented is known as type erasure and is actually used in e.g. std::function or std::any.
You should not use raw pointers and new for ownership. Use std::unique_ptr instead. Also since you only refer to the objects through the base class you need the virtual destructor. Otherwise, you won't be able to delete them correctly, again one more reason for std::unique_ptr as it deletes the pointer by itself.
If you want to get the value, what would you do with it? To quote Bjarne Stroustrup:
There is no useful universal class: a truly universal carries no semantics of its own.
Yes, you can store this value in std::any, but that's it, what would you want to do with it? Print it? Well, in that case it's no longer any but printable as in your example, so either use templates or virtual methods to express these traits in the types of the stored objects.
Consider using std::variant for known set of possible types and prefer std::any to owning void*. If you need the latter rethink your design choices first.
As others pointed out, dynamic_cast will work fine (as long as the caller knows what type is in the specific index) :
item<int>& someInt = dynamic_cast<item<int>&>(*bag.backpack[0]);
std::cout << "someInt: ";
someInt.print();
Note: You didn't provide accessor to backpack member, so I assumed it's public
Output:
someInt: 1
If I store a polymorphic functor in an std::function, is there a way to extract the functor without knowing the concrete type?
Here is a simplified version of the code:
struct Base {
//...
virtual int operator()(int foo) const = 0;
void setBar(int bar){}
};
struct Derived : Base {
//...
int operator()(int foo) const override {}
};
std::function<int(int)> getFunction() {
return Derived();
}
int main() {
auto f = getFunction();
// How do I call setBar() ?
if (Base* b = f.target<Base>()) {} // Fails: returns nullptr
else if(Derived* d = f.target<Derived>()) {
d->setBar(5); // Works but requires Derived type
}
std::cout << f(7) << std::endl;
return 0;
}
I want the client to be able to provide their own function, and for my handler to use the functionality of the Base if it's available.
The fall back would be of course to just use the abstract base class instead of std::function and clients would implement the ABC interface as they would have pre-C++11:
std::shared_ptr<Base> getFunction {
return std::make_shared<Derived>();
}
but I wanted to know if it's possible to create a more flexible and easier to use interface with C++14. It seems all that's missing is a cast inside std::function::target
It seems all that's missing is a cast inside std::function::target
All target<T> currently needs is to check target_id<T> == stored_type_info.
Being able to cast back to the real (erased) type in a context where that type may not be visible, and then check how it's related to the requested type ... is not really feasible.
Anyway, std::function is polymorphic only on the function signature. That's the thing it abstracts. If you want general-purpose polymorphism, just return a unique_ptr<Base> and use that.
If you really want function<int(int)> for the function-call syntax, instantiate it with a pimpl wrapper for unique_ptr<Base>.
Possible solution would be to have a thin wrapper:
struct BaseCaller {
BaseCaller( std::unique_ptr<Base> ptr ) : ptr_( std::move( ptr ) ) {}
int operator()( int foo ) { return (*ptr)( foo ); }
std::unique_ptr<Base> ptr_;
};
now user must create all derived from Base classed through this wrapper:
std::function<int(int)> getFunction() {
return BaseCaller( std::make_unique<Derived>() );
}
and you check in your call that target is a BaseCaller.
I want the client to be able to provide their own function, and for my handler to use the functionality of the Base if it's available.
The main drawback to using virtual dispatch is that it may create an optimization barrier. For instance, the virtual function calls cannot usually be inlined, and "devirtualization" optimizations are generally pretty difficult for the compiler to actually do in practical situations.
If you are in a situation where the code is performance critical, you can roll your own type-erasure and avoid any vtable / dynamic allocations.
I'm going to follow a pattern demonstrated in an old (but well-known) article, the "Impossibly Fast Delegates".
// Represents a pointer to a class implementing your interface
class InterfacePtr {
using ObjectPtr = void*;
using CallOperator_t = int(*)(ObjectPtr, int);
using SetBar_t = void(ObjectPtr, int);
ObjectPtr obj_;
CallOperator_t call_;
SetBar_t set_bar_;
// Ctor takes any type that implements your interface,
// stores pointer to it as void * and lambda functions
// that undo the cast and forward the call
template <typename T>
InterfacePtr(T * t)
: obj_(static_cast<ObjectPtr>(t))
, call_(+[](ObjectPtr ptr, int i) { return (*static_cast<T*>(ptr))(i); })
, set_bar_(+[](ObjectPtr ptr, int i) { static_cast<T*>(ptr)->set_bar(i); })
{}
int operator()(int i) {
return call_(obj_, i);
}
void set_bar()(int i) {
return set_bar_(obj_, i);
}
};
Then, you would take InterfacePtr instead of a pointer to Base in your API.
If you want the interface member set_bar to be optional, then you could use SFINAE to detect whether set_bar is present, and have two versions of the constructor, one for when it is, and one for when it isn't. There is recently a really great exposition of the "detection idiom" at various C++ standards on Tartan Llama's blog, here. The advantage of that would be that you get something similar to what virtual gives you, with the possibility to optionally override functions, but the dispatch decisions get made at compile-time, and you aren't forced to have a vtable. And all of the functions can potentially be inlined if the optimizer can prove to itself that e.g. in some compilation unit using this, only one type is actually passed to your API through this mechanism.
A difference is that this InterfacePtr is non-owning and doesn't have the dtor or own the storage of the object it's pointing to.
If you want InterfacePtr to be owning, like std::function, and copy the functor into its own memory and take care of deleting it when it goes out of scope, then I'd recommend to use std::any to represent the object instead of void *, and use std::any_cast in the lambdas instead of static_cast<T*> in my implementation. There's some good further discussion of std::any and why it's good for this usecase on /r/cpp here.
I don't think there's any way to do what you were originally asking, and recover the "original" functor type from std::function. Type erasure erases the type, you can't get it back without doing something squirrelly.
Edit: Another alternative you might consider is to use a type-erasure library like dyno
std::function<X>::target<T> can only cast back to exactly T*.
This is because storing how to convert to every type that can be converted to T* would require storing more information. It takes information to convert a pointer-to-derived to a pointer-to-base in the general case in C++.
target is intended to simply permit replacing some function-pointer style machinery with std::functions and have the existing machinery work, and do so with nearly zero cost (just compare typeids). Extending that cost to every base type of the stored type would have been hard, so it wasn't done, and won't be free, so it probably won't be done in the future.
std::function is, however, just an example of type erasure, and you can roll your own with additional functionality.
The first thing I'd do is I would do away with your virtual operator(). Type-erasure based polymorphism doesn't need that.
The second thing is get your hands on an any -- either boost::any or c++17's std::any.
That writes the hard part of type erasure -- small buffer optimization and value storage -- for you.
Add to that your own dispatch table.
template<class Sig>
struct my_extended_function;
template<class R, class...Args>
struct my_extended_function<R(Args...)> {
struct vtable {
R(*f)(any&, Args&&...) = 0;
void*(*cast)(any&, std::type_info const&) = 0;
};
template<class...Bases, class T>
my_extended_function make_with_bases( T t ) {
return {
get_vtable<T, Bases...>(),
std::move(t)
};
}
R operator()(Args...args)const {
return (*p_vtable->f)(state, std::forward<Args>(args)...);
}
private:
template<class T, class...Bases>
static vtable make_vtable() {
vtable ret{
// TODO: R=void needs different version
+[](any& ptr, Args&&...args)->R {
return (*any_cast<T*>(ptr))(std::forward<Args>(args)...);
},
+[](any& ptr, std::type_info const& tid)->void* {
T* pt = any_cast<T*>(ptr);
if (typeid(pt)==tid) return pt;
// TODO: iterate over Bases, see if any match tid
// implicitly cast pt to the Bases* in question, and return it.
}
};
}
template<class T, class...Bases>
vtable const* get_vtable() {
static vtable const r = make_vtable<T,Bases...>();
return &r;
}
vtable const* p_vtable = nullptr;
mutable std::any state;
my_extended_function( vtable const* vt, std::any s ):
p_vtable(vt),
state(std::move(s))
{}
};
(Note: in case this feels like an X-Y problem, scroll below the separator for how I arrived at this question)
I am looking for a way to store pointers-to-member-functions (of different types) and compare them for equality. I need to store a mapping from pointer-to-member-function to an arbitrary object, and then search this mapping. It doesn't have to be an associative container, a linear search is fine. Also note that the pointers serve as mapping keys only, they are never dereferenced.
My current approach is this: when building the mapping, I reinterpret_cast the incoming pointer-to-member to one well-known type (void (MyClass::*)()) and insert it into the mapping. Something like this (error checking omitted for brevity):
template <class R, class... A)
void CallChecker::insert(R (MyClass::*key)(A...), Object value)
{
mapping.push_back(std::make_pair(reinterpret_cast<void (MyClass::*)()>(key), value));
}
Then on lookup, I perform the same cast and search by equality:
template <class R, class... A)
Object CallChecker::retrieve(R (MyClass::*key)(A...)) const
{
auto k = reinterpret_cast<void (MyClass::*)()>(key);
auto it = std::find_if(begin(mapping), end(mapping), [k](auto x) { return x.first == k; });
return it->second;
}
However, I am not sure that this will always work. While I believe it cannot produce false negatives (two equal pointers being reported as distinct), I am afraid it might produce false negatives (two pointers which were originally of different type could compare equal when cast to the "common" type). So my question is, is that the case? Or am I safe in using comparisons like this?
I know I am treading dangerously close to UB territory here. However, I don't mind a solution which works using behaviour which is not defined by the standard, but known to work in gcc and MSVC (my two target compilers).
So, the question is: is the comparison in a common type safe? Or would I be better off casting the stored pointer to the incoming type for the comparison (like this):
template <class R, class... A)
Object CallChecker::retrieve(R (MyClass::*key)(A...)) const
{
auto it = std::find_if(begin(mapping), end(mapping), [key](auto x) { return reinterpret_cast<R (MyClass::*)(A...)>(x.first) == key; });
return it->second;
}
Or will neither of these work in practice and I'm out of luck?
I am interested in the above properties of pointers-to-member, both in light of my actual task and to deepen my understanding of the language. Still, out of a sense of completeness (and in case somebody knows a better way), here is how I arrived at the original question.
I'm building a utility framework for helping unit-testing Qt4 signals (testing that the proper signals are emitted). My idea was to create a class CallChecker that would store validators (wrapped std::function objects) for slots, and be able to run them. The test would then create a class derived from this; that class would define slots which would run the corresponding validators. Here's an idea of usage (simplified):
class MyTester : public QObject, public CallChecker
{
Q_OBJECT
public slots:
void slot1(int i, char c) { CallChecker::checkCall(&MyTester::slot1, i, c); }
void slot2(bool b) { CallChecker::checkCall(&MyTester::slot2, b); }
};
void testRunner()
{
MyTester t;
connectToTestedSignals(t);
t.addCheck(&MyTester::slot1, [](int i, char c) { return i == 7; });
}
I have a working implementation (gcc on ideone) where CallChecker uses a std::vector of pairs, with the pointers-to-member cast to a common function type. After some fiddling with compiler flags (/vmg), I got this working in MSVC as well.
If you can suggest a better solution than lookup by pointer to member, I'll be happy to hear it. My goal is ease of use in the class implementing the test slots: I really want these slots to be simple one-liners. Using a textual representation of the slot signature (what Qt uses internally) is not really an option, as it's too susceptible to typos.
As I said in the comments, there is a way to unit test that a qt signal is emitted. You need to use QSignalSpy and link to QTestLib.
As they say in their documentation :
QSignalSpy can connect to any signal of any object and records its emission. QSignalSpy itself is a list of QVariant lists. Each emission of the signal will append one item to the list, containing the arguments of the signal.
You can also read their examples, but here is one of my unit tests that use google test :
class TestSomeControls : public testing::Test
{
public:
TestSomeControls() :
obj(),
ctrl1Dis( &obj, SIGNAL(DisableControl1(bool)) ),
ctrl2Dis( &obj, SIGNAL(DisableControl2(bool)) )
{
}
model::SomeControls obj;
QSignalSpy ctrl1Dis;
QSignalSpy ctrl2Dis;
};
TEST_F( TestSomeControls, OnControl1Clicked_untilControl1Disabled )
{
for ( int i = 0; i < 5; ++ i )
{
obj.OnControl1Clicked();
ASSERT_EQ( ctrl1Dis.count(), 0 );
}
obj.OnControl1Clicked();
ASSERT_EQ( ctrl1Dis.count(), 1 );
ASSERT_EQ( ctrl1Dis.takeFirst().at(0).toBool(), true );
}
Compare anything to anything.
#include <utility>
#include <memory>
#include <iostream>
struct Base
{
virtual bool operator== (const Base& other) const = 0;
virtual ~Base() {}
};
template <class T>
struct Holder : Base
{
Holder(T t) : t(t) {}
bool operator== (const Base& other) const
{
const Holder<T>* h = dynamic_cast<const Holder<T>*>(&other);
return (h && h->t == t);
}
private:
T t;
};
struct Any
{
template<class T>
Any(T t) : p(std::make_shared<Holder<T>>(t)) {}
bool operator== (const Any& other) const
{
return *p == *other.p;
}
private:
std::shared_ptr<Base> p;
};
int main ()
{
std::cout << (Any(2) == Any(2));
std::cout << (Any(2) == Any(3));
std::cout << (Any(2) == Any("foo"));
std::cout << (Any("foo") == Any("foo"));
std::cout << (Any("foo") == Any("bar"));
}
Implementation of operator< is deferred to the reader.
Important note Two pointers-to-member of different types will always compile unequal in this implementation, but it is possible that they will be equal in direct comparison after coercion to a common type. I.e &Foo::x and &Bar::x can be the same if Foo derives from Bar. Such behaviour cannot be easily added here.
If you first check that the typeid of both sides are the same, you can then use a type-erased function to cast both sides to the same type and compare in that type. (This is strictly necessary by the standard, as even if you can round-trip via a well-known type, there is no guarantee by the standard that comparisons in that type will have the same behaviour as comparisons in the original type.) Here's a sketch:
struct any_pmf_compare {
std::type_index ti;
void (any_pmf_compare::*pmf)();
bool (*comp)(const any_pmf_compare &, const any_pmf_compare &);
template<typename F>
any_pmf_compare(F f):
ti(typeid(F)),
pmf(reinterpret_cast<void (any_pmf_compare::*)()>(f)),
comp([](const any_pmf_compare &self, const any_pmf_compare &other) {
return reinterpret_cast<F>(self.pmf) == reinterpret_cast<F>(other.pmf);
})
{
}
};
bool operator==(const any_pmf_compare &lhs, const any_pmf_compare &rhs) {
return lhs.ti == rhs.ti && lhs.comp(lhs, rhs);
}
This is a narrow answer to the narrow question.
The standard states by implication and also in a footnote that a pointer to member cannot be converted to void*. The likely rationale is that a pointer to member could require more bytes of storage than a void*. Your compiler should forbid the reinterpret cast, and even it if does not you run a real risk of clashes. You can test on your target compilers, but the risk remains.
The standard will permit you to convert a 'pointer to member of X of type T1' to 'pointer to member of Y of type T2' when T1 and T2 are both function types. In other words, your strategy is permitted as long as the common type is a pointer to member function. I think this is what you intended. S5.2.10/10 in N3337. It does not however guarantee that two such pointers will compare equal, in the way that it does for pointers to objects. For example, if the implementation includes an encoded 'this' pointer, it just won't work.
The standard will permit you to store the pointer to member in a union. You can provide a char[] member that is likely to be long enough, and you can use an assert on sizeof to make sure that it is. Provided it's a 'standard layout' type, accessing the value through the char[] should have guaranteed behaviour. Personally, I would try this just to find out how big those pointers actually are! But the problem about possible non-canonical values remains.
My third suggestion is that you use the typeid of the pointer-to-member-function instead of the pointer itself. Typeid can be applied to any expression -- if it's good enough for reinterpret_cast it's good enough for typeid -- and the resultant value should be unique to the type, not the instance.
After that I'm out of ideas. You might have to redefine/renegotiate the problem in a quest for other solutions.
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.
How do variant and any from the boost library work internally? In a project I am working on, I currently use a tagged union. I want to use something else, because unions in C++ don't let you use objects with constructors, destructors or overloaded assignment operators.
I queried the size of any and variant, and did some experiments with them. In my platform, variant takes the size of its longest possible type plus 8 bytes: I think it my just be 8 bytes o type information and the rest being the stored value. On the other hand, any just takes 8 bytes. Since i'm on a 64-bit platform, I guess any just holds a pointer.
How does Any know what type it holds? How does Variant achieve what it does through templates? I would like to know more about these classes before using them.
If you read the boost::any documentation they provide the source for the idea: http://www.two-sdg.demon.co.uk/curbralan/papers/ValuedConversions.pdf
It's basic information hiding, an essential C++ skill to have. Learn it!
Since the highest voted answer here is totally incorrect, and I have my doubts that people will actually go look at the source to verify that fact, here's a basic implementation of an any like interface that will wrap any type with an f() function and allow it to be called:
struct f_any
{
f_any() : ptr() {}
~f_any() { delete ptr; }
bool valid() const { return ptr != 0; }
void f() { assert(ptr); ptr->f(); }
struct placeholder
{
virtual ~placeholder() {}
virtual void f() const = 0;
};
template < typename T >
struct impl : placeholder
{
impl(T const& t) : val(t) {}
void f() const { val.f(); }
T val;
};
// ptr can now point to the entire family of
// struct types generated from impl<T>
placeholder * ptr;
template < typename T >
f_any(T const& t) : ptr(new impl<T>(t)) {}
// assignment, etc...
};
boost::any does the same basic thing except that f() actually returns typeinfo const& and provides other information access to the any_cast function to work.
The key difference between boost::any and boost::variant is that any can store any type, while variant can store only one of a set of enumerated types. The any type stores a void* pointer to the object, as well as a typeinfo object to remember the underlying type and enforce some degree of type safety. In boost::variant, it computes the maximum sized object, and uses "placement new" to allocate the object within this buffer. It also stores the type or the type index.
Note that if you have Boost installed, you should be able to see the source files in "any.hpp" and "variant.hpp". Just search for "include/boost/variant.hpp" and "include/boost/any.hpp" in "/usr", "/usr/local", and "/opt/local" until you find the installed headers, and you can take a look.
Edit
As has been pointed out in the comments below, there was a slight inaccuracy in my description of boost::any. While it can be implemented using void* (and a templated destroy callback to properly delete the pointer), the actualy implementation uses any<T>::placeholder*, with any<T>::holder<T> as subclasses of any<T>::placeholder for unifying the type.
boost::any just snapshots the typeinfo while the templated constructor runs: it has a pointer to a non-templated base class that provides access to the typeinfo, and the constructor derived a type-specific class satisfying that interface. The same technique can actually be used to capture other common capabilities of a set of types (e.g. streaming, common operators, specific functions), though boost doesn't offer control of this.
boost::variant is conceptually similar to what you've done before, but by not literally using a union and instead taking a manual approach to placement construction/destruction of objects in its buffer (while handling alignment issues explicitly) it works around the restrictions that C++ has re complex types in actual unions.