Iterate over class inheritances in C++ - c++

Assume I have a some classes architecture (the number of the classes is growing up during the development time), that each class inherit from N classes with the same basic interface. What is the best way (if possible) to create a base function (in the base class OR in the derived class) that will iterate over the inheritances?
Target: Avoid developers mistakes and make sure we won't forget to call all the base functions from all of the inheritances & make the code more clear to read and understandable.
Please see edit notes for updated state
Short Example:
class shared_base {
public:
virtual void func() = 0;
}
class base_1 : virtual public shared_base {
public:
void func() override {}
}
class base_2 : virtual public shared_base {
public:
void func() override {}
}
class target : virtual public base_1, virtual public base_2 {
public:
void func() override {
// Instead of:
base_1::func();
base_2::func();
// ... My func() implementation
/*
~~TODO~~
for_each(std::begin(inheritances), std::end(inheritances), [](auto& inheritance) -> void { inheritance::func(); })
~~TODO~~
*/
}
}
More descriptive & practical example:
class base {
public:
virtual void func() = 0;
/*...Some interface (pure virtual) functions...*/
}
class base_core : virtual public base {
public:
void func() override {}
/*...Some base implementations for the rest...*/
protected:
template <typename FuncT>
virtual void iterate_over_base_core_inheritances(FuncT function_to_apply) {
/*~~TODO~~*/
}
}
template <class Decorator = base_core, typename = typename std::enable_if<std::is_base_of<base_core, Decorator>::value>::type>
class core_1 : virtual public Decorator {
public:
void func() override {
// Will iterate (once) over Decorator
/*iterate_over_base_core_inheritances([](core_base*) -> void {
// Implementation
});*/
// Instead of:
Decorator::func();
}
/*More functions implementations*/
}
template <class Decorator = base_core, typename = typename std::enable_if<std::is_base_of<base_core, Decorator>::value>::type>
class core_2 : virtual public core_1<>, virtual public Decorator {
public:
void func() override {
// Will iterate (twice) over core_1 and Decorator
/*iterate_over_base_core_inheritances([](core_base*) -> void {
// Implementation
});*/
// Instead of:
Decorator::func();
core_1::func();
//... Self func() implementation
}
/*More functions implementations*/
protected:
// If it's not possible doing it in the upper hierarchy level is it possible do it here?
template <typename FuncT>
void iterate_over_base_core_inheritances(FuncT function_to_apply) override {
/*~~TODO~~*/
}
}
Some things to know:
I am working on Linux 64x platform (Ubuntu 16.04)- if it's matter for the answers.
The idea behind this code is to create kind of Decorator DP, which will be easy to extend and to understand, and also will enable the developers to use the protected functions/attributes of the base class.
A practical example (for my actual use) can be found in this commit.
Edit:
Thanks to #RaymondChen I got a working solution, with (so far) only one minor issue: Every time I want to use a class that implemented this way, I need to specify the core_base class in it's template arguments list (before- I was using the default type parameter). I am looking for a way to solve this issue.
The current solution:
template <class ...Decorators>
class core_2 : virtual public Decorators... {
public:
static_assert((std::is_base_of<base_core, Decorators>::value && ...), "All decorators must inherit from base_core class.");
void func() override {
(Decorators::func(), ...);
//... Self func() implementation
}
/*More functions implementations*/
}
Creating an instance example:
Current:
std::shared_ptr<base> base = std::make_shared<core_2<core_1<base_core>, core_3<base_core>>>();
Desired:
std::shared_ptr<base> base = std::make_shared<core_2<core_1<>, core_3<>>>();
A practical example (for my actual use) can be found in this commit.

Thanks to #RaymondChen I got really close to my original target with the following solution [See update section at the bottom]:
template <class ...Decorators>
class core_2 : virtual public Decorators... {
public:
static_assert((std::is_base_of<base_core, Decorators>::value && ...), "All decorators must inherit from base_core class.");
void func() override {
(Decorators::func(), ...);
//... Self func() implementation
}
/*More functions implementations*/
}
Explanation:
Using parameters pack we can create a "list" of classes we inherit from, and using folding expression [c++17] we can implement it in just few lines of code.
Pros compare to my original idea:
The object creation line is more clear and logically now:
Before:std::shared_ptr<base> base = std::make_shared<core_2<core_1<core_3<>>>>();
After:std::shared_ptr<base> base = std::make_shared<core_2<core_1<base_core>, core_3<base_core>>>();
Because core_1 & core_3 are independent, but core_2 is using both of them.
No need of new function in the base/derived class, it's just fit within the target line (for example in is_equal function that didn't mention within this post).
Lost functionality:
Template validation of is_base_of (Solved with static_assert & fold expressions).
Default inheritance in case that no inheritance specified is not possible yet (Still trying to solve).
Current:
std::shared_ptr<base> base = std::make_shared<core_2<core_1<base_core>, core_3<base_core>>>();
Desired:
std::shared_ptr<base> base = std::make_shared<core_2<core_1<>, core_3<>>>();
Update
After a lot of research and tries, I came up with the following solution (improved also with C++20 concepts feature):
template <class T>
concept Decorator = std::is_base_of_v<base_core, T>;
class empty_inheritance {};
template<typename Base = base_core, typename ...Decorators>
struct base_if_not_exists {
static constexpr bool value = sizeof...(Decorators);
using type = typename std::conditional<value, empty_inheritance, Base>::type;
};
template <Decorator ...Decorators>
class core_2 : virtual public base_if_not_exists<base_core, Decorators...>::type, virtual public Decorators... {
public:
void func() override {
if constexpr (!base_if_not_exists<base_core, Decorators...>::value) {
base_core::func();
}
(Decorators::func(), ...);
//... Self func() implementation
}
/*More functions implementations*/
}
No functionality lost :)

Related

Fixing object initialization so an overriden method is called

What do I have (simplified version):
template<typename T> class Watcher
{
public:
T* m_watched { nullptr };
Watcher() = default;
Watcher(T* watched) : m_watched(watched) { m_watched->addWatcher(this); };
virtual void notifyChange(int = 0) /*= 0*/{std::cout << "Watcher::notifyChange()\n";};
};
template<typename T> class Watchable
{
public:
std::vector<Watcher<T>*> m_watchers;
virtual void addWatcher(Watcher<T>* watcher)
{
m_watchers.push_back(watcher);
watcher->notifyChange();
}
};
class Config : public Watchable<Config>
{
};
class Property : public Watcher<Config>
{
public:
Property(Config* config) : Watcher<Config>(config) {};
void notifyChange(int = 0) override { std::cout << "Property::notifyChange()\n"; }
};
So when I create an instance of Property notifyChange() of the base class (Watcher) is called.
I understand why this happens, but I have no idea how to fix this still having proper modern C++ code (e.g. without making m_watched protected and so on).
You can't.
During construction of the base, the derived sub-object doesn't exist yet.
You could try making a factory function instead, which takes control of creating Propertys. Then it can instantiate in one step, and register in a second step. Make the factory function a friend as needed and have all the related machinery be otherwise private.
Vaguely related blog article

Best approach for casting pointer to method from derived to base class

We have a base class ByteCode which is intended to be generic.
Children of ByteCode are expected to write methods of the form:
void m();
The ByteCode class should have a definition for method:
typedef void (ByteCode::*Method)();
In order to execute the bytecode, we have:
void exec() {
while (true) {
uint16_t opcode = getOpcode();
Method m = opcodes[opcode];
this->*m();
}
}
Doing this in one class would be no problem. But we have the generic code in the base class, and the derived has the array:
class MyByteCodeEngine : public ByteCode {
private:
static Method opcodes[65536];
void m1() {}
void m2() {}
void m3() {}
};
Method MyByteCodeEngine ::opcodes[65536] = {
MyByteCodeEngine::m1,
MyByteCodeEngine::m2,
MyByteCodeEngine::m3
}
The problem is that these methods are not base class, they are derived. But the only instance we have is derived, We don't want to incur the overhead of virtual, we just want to cast and make this work, but the compiler is catching every trick. If it would just trust us:
Method MyByteCodeEngine ::opcodes[65536] = {
(Method)MyByteCodeEngine::m1,
(Method)MyByteCodeEngine::m2,
(Method)MyByteCodeEngine::m3
}
We can solve this problem by eliminating the ByteCode class, but this forces us to repeat the code any time we have a bytecode interpreter. Any suggestions on how to fool C++ into accepting this, cleanly?
You can use the Curiously recurring template pattern so that the base class knows about the type of the member function.
template<class T>
struct ByteCode {
typedef void (T::* Method)();
void exec() {
while (true) {
uint16_t opcode = getOpcode();
Method m = T::opcodes[opcode];
static_cast<T*>(this)->*m();
}
}
};
class MyByteCodeEngine : public ByteCode<MyByteCodeEngine > {
private:
static Method opcodes[65536];
void m1() {}
void m2() {}
void m3() {}
};
MyByteCodeEngine::Method MyByteCodeEngine ::opcodes[65536] = {
&MyByteCodeEngine::m1,
&MyByteCodeEngine::m2,
&MyByteCodeEngine::m3
}

How to automatically call a method or generate code if a subclass derived from a base class?

I have some classes that describe abilities / behaviours, such as flying, or driving etc. Each of these classes has a specific method that must be called to load some data - For example, Flyable has loadFlyData(), Drivable has loadDriveData(). For each class the method name is unique.
I have many derived classes that may inherit from one or more of these behaviour classes. Each of these derived classes has a method called loadData(), in which we should call all the parent behaviour classes methods such as loadFlyData(), loadDriveData() etc.... Is there a way to automatically generate this method using metaprogramming ? Since there are many derived classes, it may be more maintainable if I can generate these methods using metaprogramming...
Behaviour classes : (An object class may have any of these behaviours, and will have to call that classes "load" method...
class Flyable {
void loadFlyData() {
}
};
class Drivable{
void loadDriveData() {
}
};
All object classes derive from Object:
class Object {
virtual void loadData() {
}
};
A derived class:
class FlyingCar : public Object, public Flyable, public Drivable {
virtual void loadData() override {
// How to automatically generate code so that the next two lines are called:
loadFlyData();
loadDriveData();
}
};
Sure is possible. You'll need however to employ some conventions so the code can be generic. See it live.
#include <iostream>
using namespace std;
struct Flyable{
int loadConcreteData(){
cout << "Flyable\n"; return 0;
}
};
struct Drivable{
int loadConcreteData(){
cout << "Drivable\n"; return 0;
}
};
class Object{
virtual void loadData(){
}
};
template<class ...CS>
struct ConcreteLoader : Object, CS... {
void loadData() override {
int load[] = {
this->CS::loadConcreteData()...
};
}
};
class FlyingCar : public ConcreteLoader<Flyable,Drivable>{
};
int main() {
FlyingCar fc;
fc.loadData();
return 0;
}
Changes that need mentioning:
The return type of each concrete Load function had to be changed. This is to facilitate the "array trick" in expanding the parameter pack.
The names of all the load functions are the same, again for the same reason.
Reason (1) may become obsolete once c++17 and fold expressions roll out.
You can make a free function loadXData() that will become a noop if your class isn't X:
namespace detail
{
void loadFlyData(Flyable* ptr) { ptr->loadFlyData(); }
void loadFlyData(...) {}
void loadDriveData(Drivable* ptr) { ptr->loadDriveData(); }
void loadDriveData(...) {}
}
class FlyingCar : public Object, public Flyable, public Drivable{
public:
virtual void loadData()override{
//How to automatically generate code so that the next two lines are called:
detail::loadFlyData(this);
detail::loadDriveData(this);
}
};
demo
Though I think using a common name loadData and just calling it for all variadic parents might be preferable:
template<typename... Policies>
struct ComposedType : Object, Policies...
{
virtual void loadData() override {
int arr[] = {
((void)Policies::loadData(), 0)...
};
(void)arr;
}
};
using FlyingCar = ComposedType<Drivable, Flyable>;
demo
The above loadData could be simplified in C++1z:
virtual void loadData() override {
((void)Policies::loadData(), ...);
}
demo

Mapping runtime types to a parallel class hierarchy … with templates

I have two class hierarchies which have a 1:1 relationship: some normal classes A, B which have a common Root interface, and a WrapperRoot<T> interface with two concrete instantiations WrapperA<T> and WrapperB<T>. I am now looking to implement a function auto wrap<T>(Root& elem) -> unique_ptr<WrapperRoot<T>> that maps each normal class to its wrapper class.
The exact type of the wrappers is important as they will have virtual methods, and the exact type of the Root objects is not statically known.
Attempted solutions
My first idea was to declare a template virtual method in Root:
class Root {
...
public:
template<typename T>
virtual auto wrap() -> unique_ptr<WrapperRoot<T>> = 0;
}
which could then be implemented in the child classes as
class A : public Root {
...
template<typename T>
virtual auto wrap() -> unique_ptr<WrapperRoot<T>> override {
return make_unique<WrapperA<T>>();
}
}
As I was to find out, C++ does not allow templates for virtual methods. I did some further research and found the technique of type erasure, which allows us to break through this virtual vs. template dichtomy. Perhaps it might be possible to have each class select their wrapper type by passing in a visitor-like object that has erased the template parameter <T>? However, I am still fairly new to C++, and all my attempts to implement this have only moved the problem into another level, but not solved them.
This is especially frustrating since other languages which I am familiar with have no problem expressing this structure. E.g. in Java it is no problem to define a virtual method <T> WrapperRoot<T> wrap() { return new WrapperA<T>(); }, but that is because Java implements templates via reinterpreting casts. Java's implementation would be phrased in C++ as:
template<typename T>
WrapperRoot<T>* wrap() { return reinterpret_cast<WrapperRoot<T>*>(wrapper_impl()); }
virtual void* wrapper_impl() { return new WrapperA<void*>() }
However, I would like to work with the C++ type system rather than violating it by casting void pointers around.
Test Case
To phrase my problem unambiguously, I have created the below test case. Once wrap is implemented correctly, it should output this:
WrapperA
WrapperB
The main method should not be modified, but arbitrary methods, helper types, and an implementation for the wrap function may be added.
#include <iostream>
#include <memory>
using namespace std;
// the Root hierarchy
class Root {
public:
virtual ~Root() {}
};
class A : public Root {};
class B : public Root {};
// the Wrapper hierarchy
template<typename T>
class WrapperRoot {
public:
virtual ~WrapperRoot() {}
virtual T name() = 0;
};
template<typename T>
class WrapperA : public WrapperRoot<T> {
public:
virtual T name() { return T("WrapperA\n"); }
};
template<typename T>
class WrapperB : public WrapperRoot<T> {
public:
virtual T name() { return T("WrapperB\n"); }
};
// the "wrap" function I want to implement
template<typename T>
auto wrap(Root& ) -> unique_ptr<WrapperRoot<T>>;
// util
template<typename T, typename... Args>
auto make_unique(Args... args) -> unique_ptr<T> {
return unique_ptr<T>(new T(forward<Args>(args)...));
}
int main() {
unique_ptr<Root> a = make_unique<A>();
unique_ptr<Root> b = make_unique<B>();
cout << wrap<string>(*a)->name()
<< wrap<string>(*b)->name();
}
How can I make this work? Or do I need to resort to type-violating hacks?
The simplest way to get this to work would just be dynamic_casting the Root& to work out what the runtime type of it is:
template<typename T>
auto wrap(Root& root) -> unique_ptr<WrapperRoot<T>>
{
if (dynamic_cast<A*>(&root)) {
//root is an A, return a WrapperA
return make_unique<WrapperA<T>>();
}
else if (dynamic_cast<B*>(&root)) {
//root is a B, return a WrapperB
return make_unique<WrapperB<T>>();
}
throw std::runtime_error("No wrapper for that type");
}
Demo
As it turns out, this can be solved with type erasure, the Visitor Pattern, and a bit of indirection. The solution is clean, and does not require us to re-implement dynamic dispatch inside the wrap function.
The core idea is to introduce a WrapperSelector visitor interface:
class WrapperSelector {
public:
virtual auto visit(A&) -> void = 0;
virtual auto visit(B&) -> void = 0;
};
The Root hierarchy needs to be modified a bit to accept this visitor, and to perform the double dispatch:
class Root {
public:
virtual ~Root() {}
virtual auto accept(WrapperSelector&) -> void = 0;
};
class A : public Root {
public:
virtual auto accept(WrapperSelector& wrapper) -> void {
wrapper.visit(*this);
}
};
class B : public Root {
public:
virtual auto accept(WrapperSelector& wrapper) -> void {
wrapper.visit(*this);
}
};
So far, this is the bog-standard Visitor Pattern in C++. What we now do is introduce a templated class WrapperSelectorImpl<T> : public WrapperSelector. Since it is templated but only used through the un-templated interface, this implements type erasure. Internally, we construct this WrapperSelectorImpl as a container for a borrowed WrapperRoot<T> pointer, into which we write the selected wrapper. After the accept/visit sequence has ended, that pointer will be filled with the wrapper, so no virtual method needs to return a template-parameterized type. Also, the accept method does nothing but select the corresponding visit method, so the types in the Root hierarchy don't need to know about the WrapperRoot hierarchy – a concrete WrapperSelector will handle this mapping.
template<typename T>
class WrapperSelectorImpl : public WrapperSelector {
unique_ptr<WrapperRoot<T>>& _wrapper;
public:
explicit WrapperSelectorImpl(unique_ptr<WrapperRoot<T>>& wrapper)
: _wrapper(wrapper)
{}
virtual auto visit(A&) -> void override {
_wrapper = make_unique<WrapperA<T>>();
}
virtual auto visit(B&) -> void override {
_wrapper = make_unique<WrapperB<T>>();
}
};
Our wrap function must now set up a pointer, a WrapperSelectorImpl which borrows that pointer, let the given object in the Root hierarchy select the wrapper through the WrapperSelector, and return the now-populated pointer:
template<typename T>
auto wrap(Root& obj) -> unique_ptr<WrapperRoot<T>> {
unique_ptr<WrapperRoot<T>> wrapper;
WrapperSelectorImpl<T> wrapper_selector(wrapper);
obj.accept(wrapper_selector);
return wrapper;
}
Generalization
The above technique can be used to implement arbitrary templated virtual methods, or the visitor pattern with arbitrary return types. The prerequisites for this is minimal support for the Visitor Pattern`:
some Subject class or class hierarchy with a virtual void accept(SubjectVisitor& v) { v.visit(*this); }.
some SubjectVisitor interface with virtual void visit(S&) = 0 methods for each class S in the Subject class hierarchy.
Now assume we wish to implement a method with the following pseudo-signature in the Subject hierarchy:
class Subject {
...
template<typename R, typename T, typename... Args>
virtual R frobnicate(Args... args) = 0;
}
We can then use the following steps to implement this:
First, we create a wrapper function that exposes the public interface of our dispatching logic. This might be a non-virtual templated method in Subject, or a free function. The internals are the same as in the above example: Set-up of the return value, set-up of the visitor (borrowing a reference to the return value), doing the dispatch, and returning the value.
Since this is so general, we can pack this into a reusable templated function:
// most general implementation
template<typename ReturnType, typename Subject, typename Visitor, typename... Args>
auto manage_visitor(Subject& subject, Args... args) -> ReturnType {
ReturnType return_value;
Visitor visitor(return_value, std::forward(args)...);
subject.accept(visitor);
return return_value;
}
class Subject {
...
template<typename R, typename T, typename... Args>
R frobnicate(Args... args) {
return manage_visitor<R, Subject, ConcreteSubjectVisitor<R, T>>(*this, std::forward(args)...);
}
};
Note that this assumes the return value to be default-constructible. If this is not the case, substituting unique_ptr<ReturnType> for ReturnType could be a solution.
We now have to provide a class ConcreteSubjectVisitor : public SubjectVisitor that provides the actual implementation.
template<typename ReturnType, typename T>
class ConcreteSubjectVisitor : public SubjectVisitor {
ReturnType& return_value;
ArgType something;
public:
ConcreteSubjectVisitor(ReturnType& ret, ArgType& other_arg) : return_value(ret), something(other_arg) {}
virtual void visit(S1&) override { ... }
virtual void visit(S2&) override { ... }
...
};
The only thing which matters is that it can write to the return value. Note that the visitor can take additional arguments through the constructor, which makes it somewhat related to the std::bind function or to constructing a lambda. The visit definitions then contain the actual code, which has access to all type parameters of the visitor, and all constructor arguments of the visitor.
Open problems:
handling of return types that are not default-constructible (pointers or custom defaults)
specialization for void return type (problem decays to “normal” visitor pattern)
generalization to full multi-methods (trivial if method is in curried form)
providing a convenient interface
const-correctness (must be applied on a per-visitor basis, Subject::accept can be provided as const and non-const).

What are alternatives to this typelist-based class hierarchy generation code?

I'm working with a simple object model in which objects can implement interfaces to provide optional functionality. At it's heart, an object has to implement a getInterface method which is given a (unique) interface ID. The method then returns a pointer to an interface - or null, in case the object doesn't implement the requested interface. Here's a code sketch to illustrate this:
struct Interface { };
struct FooInterface : public Interface { enum { Id = 1 }; virtual void doFoo() = 0; };
struct BarInterface : public Interface { enum { Id = 2 }; virtual void doBar() = 0; };
struct YoyoInterface : public Interface { enum { Id = 3 }; virtual void doYoyo() = 0; };
struct Object {
virtual Interface *getInterface( int id ) { return 0; }
};
To make things easier for clients who work in this framework, I'm using a little template which automatically generates the 'getInterface' implementation so that clients just have to implement the actual functions required by the interfaces. The idea is to derive a concrete type from Object as well as all the interfaces and then let getInterface just return pointers to this (casted to the right type). Here's the template and a demo usage:
struct NullType { };
template <class T, class U>
struct TypeList {
typedef T Head;
typedef U Tail;
};
template <class Base, class IfaceList>
class ObjectWithIface :
public ObjectWithIface<Base, typename IfaceList::Tail>,
public IfaceList::Head
{
public:
virtual Interface *getInterface( int id ) {
if ( id == IfaceList::Head::Id ) {
return static_cast<IfaceList::Head *>( this );
}
return ObjectWithIface<Base, IfaceList::Tail>::getInterface( id );
}
};
template <class Base>
class ObjectWithIface<Base, NullType> : public Base
{
public:
virtual Interface *getInterface( int id ) {
return Base::getInterface( id );
}
};
class MyObjectWithFooAndBar : public ObjectWithIface< Object, TypeList<FooInterface, TypeList<BarInterface, NullType> > >
{
public:
// We get the getInterface() implementation for free from ObjectWithIface
virtual void doFoo() { }
virtual void doBar() { }
};
This works quite well, but there are two problems which are ugly:
A blocker for me is that this doesn't work with MSVC6 (which has poor support for templates, but unfortunately I need to support it). MSVC6 yields a C1202 error when compiling this.
A whole range of classes (a linear hierarchy) is generated by the recursive ObjectWithIface template. This is not a problem for me per se, but unfortunately I can't just do a single switch statement to map an interface ID to a pointer in getInterface. Instead, each step in the hierarchy checks for a single interface and then forwards the request to the base class.
Does anybody have suggestions how to improve this situation? Either by fixing the above two problems with the ObjectWithIface template, or by suggesting alternatives which would make the Object/Interface framework easier to use.
dynamic_cast exists within the language to solve this exact problem.
Example usage:
class Interface {
virtual ~Interface() {}
}; // Must have at least one virtual function
class X : public Interface {};
class Y : public Interface {};
void func(Interface* ptr) {
if (Y* yptr = dynamic_cast<Y*>(ptr)) {
// Returns a valid Y* if ptr is a Y, null otherwise
}
if (X* xptr = dynamic_cast<X*>(ptr)) {
// same for X
}
}
dynamic_cast will also seamlessly handle things like multiple and virtual inheritance, which you may well struggle with.
Edit:
You could check COM's QueryInterface for this- they use a similar design with a compiler extension. I've never seen COM code implemented, only used the headers, but you could search for it.
What about something like that ?
struct Interface
{
virtual ~Interface() {}
virtual std::type_info const& type() = 0;
};
template <typename T>
class InterfaceImplementer : public virtual Interface
{
std::type_info const& type() { return typeid(T); }
};
struct FooInterface : InterfaceImplementer<FooInterface>
{
virtual void foo();
};
struct BarInterface : InterfaceImplementer<BarInterface>
{
virtual void bar();
};
struct InterfaceNotFound : std::exception {};
struct Object
{
void addInterface(Interface *i)
{
// Add error handling if interface exists
interfaces.insert(&i->type(), i);
}
template <typename I>
I* queryInterface()
{
typedef std::map<std::type_info const*, Interface*>::iterator Iter;
Iter i = interfaces.find(&typeid(I));
if (i == interfaces.end())
throw InterfaceNotFound();
else return static_cast<I*>(i->second);
}
private:
std::map<std::type_info const*, Interface*> interfaces;
};
You may want something more elaborate than type_info const* if you want to do this across dynamic libraries boundaries. Something like std::string and type_info::name() will work fine (albeit a little slow, but this kind of extreme dispatch will likely need something slow). You can also manufacture numeric IDs, but this is maybe harder to maintain.
Storing hashes of type_infos is another option:
template <typename T>
struct InterfaceImplementer<T>
{
std::string const& type(); // This returns a unique hash
static std::string hash(); // This memoizes a unique hash
};
and use FooInterface::hash() when you add the interface, and the virtual Interface::type() when you query.