#include <iostream>
#include <unordered_set>

template < typename T > struct magic
{
    magic() { objects.insert( static_cast<T*>(this) ) ; }
    magic( const magic& ) : magic() {}
    magic( magic&& ) : magic() {}
    ~magic() { objects.erase( static_cast<T*>(this) ) ; }

    template< typename FN > static void for_each_instance( FN fn )
    { for( T* p : objects ) fn(p) ; }

    static std::unordered_set<T*> objects ;
};

template < typename T > std::unordered_set<T*> magic<T>::objects ;

struct A : magic<A>
{
    void foo( int i, char c )
    { std::cout << "A::foo( " << this << ", " << i << ", " << c << " )\n" ; }
};

struct B : magic<B>
{
    void bar( double d ) const
    { std::cout << "B::bar( " << this << ", " << d << " )\n" ; }
};

int main()
{
    A one ;
    B two ;
    {
        A three = one ;
        B b[2] ;
        A::for_each_instance( []( A* p ) { p->foo( 99, 'X' ) ; } ) ;
        B::for_each_instance( []( B* p ) { p->bar( 12.8 ) ; } ) ;
    }
    std::cout << "------------------------\n" ;
    A::for_each_instance( []( A* p ) { p->foo( -7, 'Y' ) ; } ) ;
    B::for_each_instance( []( B* p ) { p->bar( 123.45 ) ; } ) ;
}
