I realize that I\'ll most likely get a lot of \"you shouldn\'t do that because...\" answers and they are most welcome and I\'ll probably totally agree with your reasoning, but I
This can be a solution, using RTTI polymorphism
#include #include #include #include namespace dynamic { template T& enforce(T& z, const E& e) { if(!z) throw e; return z; } template const T& enforce(const T& z, const E& e) { if(!z) throw e; return z; } template class interface; class aggregate; //polymorphic uncopyable unmovable class property { public: property() :pagg() {} property(const property&) =delete; property& operator=(const property&) =delete; virtual ~property() {} //just make it polymorphic template operator Interface*() const { if(!pagg) return 0; return *pagg; //let the aggregate do the magic! } aggregate* get_aggregate() const { return pagg; } private: template friend class interface; friend class aggregate; static unsigned gen_id() { static unsigned x=0; return enforce(++x,std::overflow_error("too many ids")); } template static unsigned id_of() { static unsigned z = gen_id(); return z; } aggregate* pagg; }; template class interface: public property { public: interface() {} virtual ~interface() {} unsigned id() const { return property::id_of(); } }; //sealed movable class aggregate { public: aggregate() {} aggregate(const aggregate&) = delete; aggregate& operator=(const aggregate&) = delete; aggregate(aggregate&& s) :m(std::move(s.m)) {} aggregate& operator=(aggregate&& s) { if(this!=&s) { m.clear(); std::swap(m, s.m); } return *this; } template aggregate& add_interface(interface* pi) { m[pi->id()] = std::unique_ptr(pi); static_cast(pi)->pagg = this; return *this; } template aggregate& remove_interface() { m.erase[property::id_of()]; return *this; } void clear() { m.clear(); } bool empty() const { return m.empty(); } explicit operator bool() const { return empty(); } template operator Interface*() const { auto i = m.find(property::id_of()); if(i==m.end()) return nullptr; return dynamic_cast(i->second.get()); } template friend aggregate& operator<<(aggregate& s, interface* pi) { return s.add_interface(pi); } private: typedef std::map > map_t; map_t m; }; } /// this is a sample on how it can workout class interface_A: public dynamic::interface { public: virtual void methodA1() =0; virtual void methodA2() =0; }; class impl_A1: public interface_A { public: impl_A1() { std::cout<<"creating impl_A1["< { public: virtual void methodB1() =0; virtual void methodB2() =0; }; class impl_B1: public interface_B { public: impl_B1() { std::cout<<"creating impl_B1["<methodA1(); pa->methodA2(); } pb = *pa; if(pb) { pb->methodB1(); pb->methodB2(); } pa = agg2; if(pa) { pa->methodA1(); pa->methodA2(); } pb = *pa; if(pb) { pb->methodB1(); pb->methodB2(); } agg2 = std::move(agg1); pa = agg2; if(pa) { pa->methodA1(); pa->methodA2(); } pb = *pa; if(pb) { pb->methodB1(); pb->methodB2(); } return 0; }
tested with MINGW4.6 on WinXPsp3