We have a sub-project 'commonUtils' that has many generic code-snippets used across the parent project.
One such interesting stuff i saw was :-
/*********************************************************************
If T is polymorphic, the compiler is required to evaluate the typeid
stuff at runtime, and answer will be true. If T is non-polymorphic,
the compiler is required to evaluate the typeid stuff at compile time,
whence answer will remain false
*********************************************************************/
template <class T>
bool isPolymorphic() {
bool answer=false;
typeid(answer=true,T());
return answer;
}
I believed the comment and thought that it is quite an interesting template though it is not
used across the project. I tried using it like this just for curiosity ...
class PolyBase {
public:
virtual ~PolyBase(){}
};
class NPolyBase {
public:
~NPolyBase(){}
};
if (isPolymorphic<PolyBase>())
std::cout<<"PolyBase = Polymorphic\n";
if (isPolymorphic<NPolyBase>())
std::cout<<"NPolyBase = Also Polymorphic\n";
But none of those ever returns true. MSVC 2005 gives no warnings but Comeau warns typeid expression has no effect. Section 5.2.8 in the C++ standard does not say anything like what the comment says i.e. typeid is is evaluated at compile time for non-polymorphic types and at runtime for polymorphic types.
1) So i guess the comment is misleading/plain-wrong or since the author of this code is quite a senior C++ programmer, am i missing something?
2) OTOH, I am wondering if we can test whether a class is polymorphic(has at least one virtual function) using some technique?
3) When would one want to know if a class is polymorphic? Wild guess; to get the start-address of a class by using dynamic_cast<void*>(T) (as dynamic_cast works only on polymorphic classes).
Awaiting your opinions.
Thanks in advance,
I cannot imagine any possible way how that typeid could be used to check that type is polymorphic. It cannot even be used to assert that it is, since typeid will work on any type.
Boost has an implementation here. As for why it might be necessary -- one case I know is the Boost.Serialization library. If you are saving non-polymorphic type, then you can just save it. If saving polymorphic one, you have to gets its dynamic type using typeid, and then invoke serialization method for that type (looking it up in some table).
Update: it appears I am actually wrong. Consider this variant:
template <class T>
bool isPolymorphic() {
bool answer=false;
T *t = new T();
typeid(answer=true,*t);
delete t;
return answer;
}
This actually does work as name suggests, exactly per comment in your original code snippet. The expression inside typeid is not evaluated if it "does not designate an lvalue of polymorphic class type" (std 3.2/2). So, in the case above, if T is not polymorphic, the typeid expression is not evaluated. If T is polymorphic, then *t is indeed lvalue of polymorphic type, so entire expression has to be evaluated.
Now, your original example is still wrong :-). It used T(), not *t. And T() create rvalue (std 3.10/6). So, it still yields an expression that is not "lvalue of polymorphic class".
That's fairly interesting trick. On the other hand, its practical value is somewhat limited -- because while boost::is_polymorphic gives you a compile-time constant, this one gives you a run-time value, so you cannot instantiate different code for polymorphic and non-polymorphic types.
Since C++11, this is now available in the <type_traits> header as std::is_polymorphic. It can be used like this:
struct PolyBase {
virtual ~PolyBase() {}
};
struct NPolyBase {
~NPolyBase() {}
};
if (std::is_polymorphic<PolyBase>::value)
std::cout << "PolyBase = Polymorphic\n";
if (std::is_polymorphic<NPolyBase>::value)
std::cout << "NPolyBase = Also Polymorphic\n";
This prints just "PolyBase = Polymorphic".
class PolyBase {
public:
virtual ~PolyBase(){}
};
class NPolyBase {
public:
~NPolyBase(){}
};
template<class T>
struct IsPolymorphic
{
struct Derived : T {
virtual ~Derived();
};
enum { value = sizeof(Derived)==sizeof(T) };
};
void ff()
{
std::cout << IsPolymorphic<PolyBase >::value << std::endl;
std::cout << IsPolymorphic<NPolyBase>::value << std::endl;
}
One can use the facts that:
dynamic_cast fails at compile time if the argument is not a polymorphic class. So that it can be used with SFINAE.
dynamic_cast<void*> is a valid cast that returns the address of the complete polymorpic object.
Hence, in C++11:
#include <iostream>
#include <type_traits>
template<class T>
auto is_polymorphic2_test(T* p) -> decltype(dynamic_cast<void*>(p), std::true_type{});
template<class T>
auto is_polymorphic2_test(...) -> std::false_type;
template<class T>
using is_polymorphic2 = decltype(is_polymorphic2_test<T>(static_cast<T*>(0)));
struct A {};
struct B { virtual ~B(); };
int main() {
std::cout << is_polymorphic2<A>::value << '\n'; // Outputs 0.
std::cout << is_polymorphic2<B>::value << '\n'; // Outputs 1.
}
I'm a little confused here, and am hoping to get some comments on this answer explaining what I'm missing.
Surely if you want to find out whether a class is polymorphic, all you have to do is ask whether it supports dynamic_cast, isn't that right?
template<class T, class> struct is_polymorphic_impl : false_type {};
template<class T> struct is_polymorphic_impl
<T, decltype(dynamic_cast<void*>(declval<T*>()))> : true_type {};
template<class T> struct is_polymorphic :
is_polymorphic_impl<remove_cv_t<T>, void*> {};
Can anyone point out a flaw in this implementation? I imagine there must be one, or must have been one at some point in the past, because the Boost documentation continues to claim that is_polymorphic "can't be portably implemented in the C++ language".
But "portably" is kind of a weasel word, right? Maybe they're just alluding to how MSVC doesn't support expression-SFINAE, or some dialects such as Embedded C++ don't support dynamic_cast. Maybe when they say "the C++ language" they mean "a lowest-common-denominator subset of the C++ language." But I have a nagging suspicion that maybe they mean what they say, and I'm the one who's missing something.
The typeid approach in the OP (as amended by a later answer to use an lvalue not an rvalue) also seems fine, but of course it's not constexpr and it requires actually constructing a T, which might be super expensive. So this dynamic_cast approach seems better... unless it doesn't work for some reason. Thoughts?
Related
I have the following piece of code :
template<typename T>
class genericHandler{public: using evt_t = T;};
template<typename T>
class specialHandler : public genericHandler<T> { /* more stuff */ };
int main(int argc, char *argv[]) {
std::any any_var = specialHandler<int>{};
auto f = [&any_var](auto evtHandler) {
using EventType = typename std::remove_reference<decltype(evtHandler)>::type ::evt_t;
if(any_var.type() == typeid(EventType)) { std::cout << "yes" << std::endl; } else { std::cout << "no" << std::endl; }
};
auto h = specialHandler<int>{ };
f(h);
}
Try it on Coliru
When called, evtHandler is of non-polymorphic derived type specialHandler. According to cppreference, we have :
When applied to an expression of polymorphic type, evaluation of a
typeid expression may involve runtime overhead (a virtual table
lookup), otherwise typeid expression is resolved at compile time.
When I compile with gcc and -fno-rtti, I get the following error message :
cannot use 'typeid' with '-fno-rtti'
RTTI is run-time type information, which should not be needed in the case of non-polymorphic typeid that can be deduced at compile-time. Did I miss something ?
You're asking two questions.
RTTI is run-time type information, which should not be needed in the case of non-polymorphic typeid ...
But this is a compiler switch, not a language feature, so you should check the compiler documentation:
-fno-rtti
Disable generation of information about every class with virtual functions for use by the C++ runtime type identification features (dynamic_cast and typeid). If you don't use those parts of the language, you can save some space by using this flag. Note that exception handling uses the same information, but it will generate it as needed. The dynamic_cast operator can still be used for casts that do not require runtime type information, i.e. casts to void * or to unambiguous base classes.
(my emphasis).
So the switch disables the entire typeinfo system to save space. If you want typeinfo (or you want to use a standard library facility that uses typeinfo), then don't explicitly disable typeinfo with a compiler option.
... non-polymorphic typeid that can be deduced at compile-time
Edit, as Mr. Wakely points out, the issue is that you're explicitly using typeid in your own code.
Although std::any may be capable of erasing the stored type from the top-level object without RTTI, this is implementation-dependent, and it definitely can't implement std::any::type() without using the typeid/typeinfo you told GCC not to generate.
Oh, and I forgot
Did I miss something ?
Yes, to ask your actual question, which is
I'm erasing it because I need to solve a circular template dependency, sadly I am not free to 'simply not erase it' here. Do I have any alternative that doesn't use RTTI
Sure, type erasure doesn't depend on RTTI.
Only automated type erasure depends on RTTI and, as above, not all of that. You can either avoid std::any::type() or write your own discriminated union by hand - you'd need to enumerate your types, but only the enumeration itself needs to be visible to all users of the DU.
It is possible to altered your code not use std::any::type(). In such case everything works as expected (after fixing some other issue in your code):
#include <iostream>
#include <any>
template<typename T>
class genericHandler{public: using evt_t = T;};
template<typename T>
class specialHandler : public genericHandler<T> { /* more stuff */ };
int main(int argc, char *argv[]) {
std::any any_var = specialHandler<int>{};
auto f = [&any_var](auto evtHandler) {
using EventType = typename std::remove_reference<decltype(evtHandler)>::type ::evt_t;
std::cout << (std::any_cast<specialHandler<EventType>>(&any_var) != nullptr ? "yes" : "no") << std::endl;
};
auto h = specialHandler<int>{ };
f(h);
f(specialHandler<double>{});
}
Works when RTTI is disabled:
http://coliru.stacked-crooked.com/a/20855b15701605f1
While learning Vulkan I came across some code in the VulkanCookbook. in the VulkanCookbook the author writes the code to import the Vulkan functions and classes by hand. Well I've been slowly converting it over to the LunarG's SDK for Vulkan and I came across a problem in the under 64bit VkFence it typedef'd to VkFence_T* which is fine and all but in 32bit it's typedef'd as uint64_t which causes a problem for VkDestroyer which uses code similar to below
#include <iostream>
#include <stdint.h>
typedef uint64_t A;
typedef uint64_t B;
template<typename T>
class Handler
{
void DestroyObject( T parent );
};
template<>
inline void Handler<A>::DestroyObject(A object) {
std::cout << "destroy type A" << std::endl;
}
template<>
inline void Handler<B>::DestroyObject(B object) {
std::cout << "destroy type B!" << std::endl;
}
int main()
{}
is there any good way to handle this problem or do I have to go and rework all the example code to delete Objects by hand? I would like to compile under 32bit if possible.
Sorry if this question has been asked somewhere else I couldn't find it as google always came partial templating and other non-related topics. And I do understand the problem with the code the compiler is looking at _A and _B and just treating it a uint64_t without caring that they are named differently, which causes the DestroyObject overloads to be for the same template type causing the redefinition error.
Edit: fixed the code using invalid naming as that wasn't actually a core problem.
C++ doesn't have strong typedefs. A type alias is simply another name for an existing type, and is entirely equivalent to the type it aliases, when used.
You need A and B to be actual types, not aliases, which are both in a relationship with uint64_t. So long as you constrain yourself to integral types, you can construct new distinct ones out of them.
The solution is an enumeration with an underlying type specified for it.
#include <type_traits>
template<typename E>
using argument_t = std::conditional_t<std::is_enum<E>::value,
std::underlying_type_t<E>,
E>;
template<typename T>
class Handler
{
void DestroyObject( argument_t<T> parent );
};
enum A : uint64_t {};
enum B : uint64_t {};
template<>
inline void Handler<A>::DestroyObject(uint64_t object) {
std::cout << "destroy type A" << std::endl;
}
template<>
inline void Handler<B>::DestroyObject(uint64_t object) {
std::cout << "destroy type B!" << std::endl;
}
The above works like this:
The argument_t utility checks if E is an enumeration, and gives the underlying type for it. Otherwise it falls back to E itself.
The primary template accepts a T, and transforms the argument if needed.
Since A and B are distinct types now, you can specialize on each. The function accepts the underlying type as a parameter.
You almost have it right... What the above functions Handler<_A>::DestroyObject(_A object) and Handler<_B>::DestroyObject(_B object) actually are is concrete instantiations of a templated member function. Because the author did not provide a generic version of this function, you are having the issues you are with trying to instantiate the class with a uint32_t. The simple fix would be to write a template<> void Handler<uint32_t>::DestroyObject(uint32_t o) function. Without more context, I cannot offer better advice.
There is no way for a template to distinguish between being pasded A and B as a type parameter.
There may be alternatives to manually cleaning up objects, but your question is too vague and focused on finding a way to get a non-viable solition working to determine what your problem really is.
Probably you have to disntinguish between the types using something different than the types themselves.
Is there a way to check if class has a typedef which works even for private typedef?
Following code works in VS2013, but fails on ideone's gcc
template<typename T>
struct to_void
{
typedef void type;
};
class Foo
{
typedef int TD;
};
template <typename T, typename dummy = void>
struct has_TD : std::false_type {};
template <typename T>
struct has_TD<T, typename to_void<typename T::TD>::type > : std::true_type{};
int main()
{
std::cout << std::boolalpha << has_TD<Foo>::value << std::endl;
}
edit - why I want this
I have custom serialization system, which can serialize arbitrary type. It has several overloads when it must behave differently (for example string). For the rest of the types, it simply writes the value in the memory. If I have composed type, I can sometimes just write into memory as well (save & load happens on the same architecture, compiled with the same compiler, so paddings will be the same, etc.). This method is valid for example for POD types (std::is_pod trait), but all POD types is only a subset of all types, supporting this serialization.
So I basically have templated function write<T> which just write sizeof(T) bytes (raw-serialization)... But I don't want this to be called by mistake, I want user, to explicitly say in their class: "this class/struct can be raw-serialized"). The way I do it is a macro ALLOW_RAW_SERIALIZE which defines some typedef which can be checked via trait. If class MyClass doesn't contains typedef, calling write(myClassInstance) will produce compiler error.
The things which which basically decide if class can be raw-serialized are its members (without reflection, members cannot be enumerated and checked automatically, so user have to provide such information). typical class looks like this:
class
public
ctor-dtor
methods
private
methods
members
and I want users to allow write ALLOW_RAW_SERIALIZE as close to the members as possible, so when they change some members there is a lesser chance to forgot about updating ALLOW_RAW_SERIALIZE (remove it. when it's no longer valid)
So that is why I want to check a private typedef
Since it's substitute for reflection and takes whole type and write it, I don't fell about it like breaking encapsulation or so...
UPDATE:
Okay, did a little research.
FYI, the [probable] reason that ideone didn't compile is that what you're doing needs -std=c++11 [or higher]. I got similar errors before adding that. But, I had to use clang++ as g++ still had problems compiling if TD was private.
But, I'm not sure this works as the only combo that printed true was if TD was public. All others of public/private and changing TD to TF produced false. Maybe VS2013 works [why?], but two other compilers have issues, either in compilation or runtime results--YMMV.
The basis for what you're doing is std::integral_constant [since c++11]. There appears to be no standard derivation from this for what you're doing. That is, from http://www.cplusplus.com/reference/type_traits/integral_constant/ the list of type traits [on the left] has nothing that matches your use case [AFAICT].
Nor does Boost.TypeTraits have anything that matches up [again, AFAICT].
From Andrei Alexandrescu's book: "Modern C++ Design: Generic Programming and Design Patterns Applied", section 2.10 Type Traits:
Usually, you will write your own trait templates and classes as your generic code needs them. Certain traits, however, are applicable to any type. They can help generic programmers to tailor template code better to the capabilities of a type.
So, it's "okay" to roll your own, if you wish.
But, even the TypeTraits he talks about [from Loki], again, doesn't have anything that matches what you're doing.
Since neither std nor Boost has anything, then the question becomes "what is standard?" [from your perspective]. There may be "fludger" c++ traits library somewhere that has an implementation, but would that be considered "standard"? YMMV
However, a question or two:
Why would one do this? What is the use for it? What about a protected typedef in a base class?
And, this seems to require knowledge of the private part of a class, and wouldn't that be a violation of either "data hiding" or encapsulation [without a friend declaration of some sort]?
So, if that last question is true, the probable [IMO] answer is that there is no standard way to do this, because it's not something one should be doing in a standard library.
Side note: This is the part that got downvoted (before I [truly] understood the question). I believe I've acquitted myself above. So, disregard the answer below.
When you use class the default visibility is private. With struct, it's public.
So, either do:
struct Foo
Or:
class Foo
{
public:
typedef int TD;
};
This is, of course, assuming that you want TD to be public
If all you need is compile time checking then following code should do:
#include <iostream>
class Foo
{
typedef int TD;
template<typename T> friend class has_TD;
};
template <typename T>
struct has_TD
{
typedef typename T::TD type;
};
template <typename T, typename has_TD<T>::type = 0>
void write(const T& /*data*/)
{
std::cout << "serialize" << std::endl;
}
int main()
{
Foo foo;
write(foo);
}
This question is in spirit a follow-on from this question from another user, which has some excellent answers:
Is it possible to write a template to check for a function's existence?
I want to do exactly what is described in this question, except I want to be able to do it for a constructor. Eg, given these two types:
class NormalType
{
public:
NormalType()
{
std::cout << "NormalType::NormalType()" << std::endl;
}
};
class SpecialType
{
public:
SpecialType()
{
std::cout << "SpecialType::SpecialType()" << std::endl;
}
SpecialType(int someArg)
{
std::cout << "SpecialType::SpecialType(int someArg)" << std::endl;
}
};
And this helper function for constructing an object:
template<class T>
class ConstructHelper
{
public:
template<bool HasSpecialConstructor>
static T Construct()
{
return T();
}
template<>
static T Construct<true>()
{
return T(int(42));
}
};
I want to be able to write code like this:
NormalType normalType = ConstructHelper<NormalType>::Construct<has_special_constructor<NormalType>::value>();
SpecialType specialType = ConstructHelper<SpecialType>::Construct<has_special_constructor<SpecialType>::value>();
Where the desired results are that NormalType::NormalType() is called, and SpecialType::SpecialType(int someArg) is called. The missing ingredient here is that critical has_special_constructor helper, which can determine if our special constructor exists for a given type.
The previous question I referenced deals with checking if a given function exists on a type, and there were a variety of working solutions presented. Unfortunately, most of them rely on being able to take the address of the target method, and as per the C++ spec, you can't take the address of a constructor (12.1.10). Of the remaining working solutions, all of them seem to rely on SFINAE with decltype on an arbitrary expression in a template specialization. That is a simple way to solve this problem, but unfortunately I'm working on Visual Studio 2013, which doesn't properly support the C++11 SFINAE rules, and still won't with the release of "Visual Studio 14" either. With proper SFINAE support, I should be able to do this for example:
template<class T>
struct has_special_constructor
{
template<class S>
struct calculate_value: std::false_type {};
template<>
struct calculate_value<decltype(T(int(42)))>: std::true_type {};
static const bool value = calculate_value<T>::value;
};
But that won't compile under VS2013 if I try and test a type that doesn't define my target constructor, due to the lack of SFINAE support. That said, I'm not yet convinced this is impossible, I think there might be a way to make it work, but I haven't been able to find a solution so far. Anyone out there see a way to do this that I've overlooked?
Here's some more info about what I'd need in order to accept an answer as a solution to this problem:
It must be possible to resolve has_special_constructor<T>::value for any given type without additional code being written for that specific type.
I'm primarily targeting Visual Studio 2013, so any solution must work in that environment. I know a fully conforming C++11 compiler could manage this problem more easily, but I'm looking for something that can function now on my current target compiler.
If anyone can supply a solution that works in a C++03 compiler (IE, without any C++11 features) I'll accept that over one that uses C++11 features.
I'd settle for a MSVC extension-based workaround at this point, since I can use the preprocessor to fall back to this method until full C++11 support comes along.
template<class T>
using has_special_constructor = std::is_constructible<T, int>;
Possible "C++03" version:
template <class T>
struct has_special_constructor {
typedef char one;
typedef struct { char _[2];} two;
template <std::size_t>
struct dummy {};
template<class U>
static one f(dummy<sizeof(U(42))>*);
template<class>
static two f(...);
static const bool value = sizeof(f<T>(0)) == sizeof(one);
};
This works on g++ 4.4 or later in C++03 mode. I put "C++03" is in scary quotes since this depends on expression SFINAE, which seems to be a bit of a gray area in C++03 - apparently C++03's wording seemed to allow it, but no major compiler vendor actually supported it until C++11 is almost here (GCC 4.4 was released in 2009), so it's arguable whether "pure" C++03 allows it...
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.