#include <iostream>
#include <unordered_set>
#include <memory>
template < typename T, typename TAG = void > struct magic
{
magic() { objects.insert( static_cast<T*>(this) ) ; }
magic( const magic& that ) : magic() {}
magic( magic&& that ) : magic() {}
~magic() { objects.erase( static_cast<T*>(this) ) ; }
template< typename FN > static void for_each_instance( FN fn )
{ for( T* p : objects ) fn(p) ; }
private: static std::unordered_set<T*> objects ;
};
template < typename T, typename TAG > std::unordered_set<T*> magic<T,TAG>::objects ;
template < typename T, typename TAG = void > struct tracked
: T, magic< tracked<T,TAG>, TAG >
{
template < typename ... ARGS > tracked( ARGS... args ) : T(args...) {}
};
struct A
{
virtual ~A() {}
void foo( int i, char c )
{ std::cout << "A::foo( " << this << ", " << i << ", " << c << " )\n" ; }
};
struct B
{
B( int a = 0, double b = 0 ) {}
virtual ~B() {}
void bar( const char* cstr )
{ std::cout << "B::bar( " << this << ", " << cstr << " )\n" ; }
};
int main()
{
A not_tracked[10] ;
B also_not_tracked[20] ;
std::unique_ptr<A> default_tracked( new tracked<A> ) ;
std::unique_ptr<B> also_default_tracked( new tracked<B> ) ;
struct my_objects {};
A* my_tracked_A_objects = new tracked< A, my_objects >[2] ;
tracked< B, my_objects > my_tracked_B_objects[3] { {1,2.3}, {4,5.6}, {7,8.9} } ;
struct their_objects {};
tracked< A, their_objects > their_tracked_A_objects[4] ;
std::cout << "tracked A (default)\n-----------------------\n" ;
tracked<A>::for_each_instance( []( A* pa ) { pa->foo( 1, 'x' ) ; } ) ;
std::cout << "\ntracked A (my_objects)\n---------------------\n" ;
tracked<A,my_objects>::for_each_instance( []( A* pa ) { pa->foo( 2, 'y' ) ; } ) ;
std::cout << "\ntracked A (their_objects)\n--------------\n" ;
tracked<A,their_objects>::for_each_instance( []( A* pa ) { pa->foo( 3, 'z' ) ; } ) ;
std::cout << "\ntracked B (my_objects)\n--------------\n" ;
tracked<B,my_objects>::for_each_instance( []( B* pb ) { pb->bar( "hello" ) ; } ) ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dW5vcmRlcmVkX3NldD4KI2luY2x1ZGUgPG1lbW9yeT4KCnRlbXBsYXRlIDwgdHlwZW5hbWUgVCwgdHlwZW5hbWUgVEFHID0gdm9pZCAgPiBzdHJ1Y3QgbWFnaWMKewogICAgbWFnaWMoKSB7IG9iamVjdHMuaW5zZXJ0KCBzdGF0aWNfY2FzdDxUKj4odGhpcykgKSA7IH0KCiAgICBtYWdpYyggY29uc3QgbWFnaWMmIHRoYXQgKSA6IG1hZ2ljKCkge30KCiAgICBtYWdpYyggbWFnaWMmJiB0aGF0ICkgOiBtYWdpYygpIHt9CgogICAgfm1hZ2ljKCkgeyBvYmplY3RzLmVyYXNlKCBzdGF0aWNfY2FzdDxUKj4odGhpcykgKSA7IH0KCiAgICB0ZW1wbGF0ZTwgdHlwZW5hbWUgRk4gPiBzdGF0aWMgdm9pZCBmb3JfZWFjaF9pbnN0YW5jZSggRk4gZm4gKQogICAgeyBmb3IoIFQqIHAgOiBvYmplY3RzICkgZm4ocCkgOyB9CgogICAgcHJpdmF0ZTogc3RhdGljIHN0ZDo6dW5vcmRlcmVkX3NldDxUKj4gb2JqZWN0cyA7Cn07Cgp0ZW1wbGF0ZSA8IHR5cGVuYW1lIFQsIHR5cGVuYW1lIFRBRyA+IHN0ZDo6dW5vcmRlcmVkX3NldDxUKj4gbWFnaWM8VCxUQUc+OjpvYmplY3RzIDsKCnRlbXBsYXRlIDwgdHlwZW5hbWUgVCwgdHlwZW5hbWUgVEFHID0gdm9pZCA+IHN0cnVjdCB0cmFja2VkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IFQsIG1hZ2ljPCB0cmFja2VkPFQsVEFHPiwgVEFHID4KewogICAgdGVtcGxhdGUgPCB0eXBlbmFtZSAuLi4gQVJHUyA+IHRyYWNrZWQoIEFSR1MuLi4gYXJncyApIDogVChhcmdzLi4uKSB7fQp9OwoKc3RydWN0IEEKewogICAgdmlydHVhbCB+QSgpIHt9CiAgICB2b2lkIGZvbyggaW50IGksIGNoYXIgYyApCiAgICB7IHN0ZDo6Y291dCA8PCAiQTo6Zm9vKCAiIDw8IHRoaXMgPDwgIiwgIiA8PCBpIDw8ICIsICIgPDwgYyA8PCAiIClcbiIgOyB9Cn07CgpzdHJ1Y3QgQgp7CiAgICBCKCBpbnQgYSA9IDAsIGRvdWJsZSBiID0gMCApIHt9CiAgICB2aXJ0dWFsIH5CKCkge30KICAgIHZvaWQgYmFyKCBjb25zdCBjaGFyKiBjc3RyICkKICAgIHsgc3RkOjpjb3V0IDw8ICJCOjpiYXIoICIgPDwgdGhpcyA8PCAiLCAiIDw8IGNzdHIgPDwgIiApXG4iIDsgfQp9OwoKaW50IG1haW4oKQp7CiAgICBBIG5vdF90cmFja2VkWzEwXSA7CiAgICBCIGFsc29fbm90X3RyYWNrZWRbMjBdIDsKCiAgICBzdGQ6OnVuaXF1ZV9wdHI8QT4gZGVmYXVsdF90cmFja2VkKCBuZXcgdHJhY2tlZDxBPiApIDsKICAgIHN0ZDo6dW5pcXVlX3B0cjxCPiBhbHNvX2RlZmF1bHRfdHJhY2tlZCggbmV3IHRyYWNrZWQ8Qj4gKSA7CgogICAgc3RydWN0IG15X29iamVjdHMge307CiAgICBBKiBteV90cmFja2VkX0Ffb2JqZWN0cyA9IG5ldyB0cmFja2VkPCBBLCBteV9vYmplY3RzID5bMl0gOwogICAgdHJhY2tlZDwgQiwgbXlfb2JqZWN0cyA+IG15X3RyYWNrZWRfQl9vYmplY3RzWzNdIHsgezEsMi4zfSwgezQsNS42fSwgezcsOC45fSB9IDsKCiAgICBzdHJ1Y3QgdGhlaXJfb2JqZWN0cyB7fTsKICAgIHRyYWNrZWQ8IEEsIHRoZWlyX29iamVjdHMgPiB0aGVpcl90cmFja2VkX0Ffb2JqZWN0c1s0XSA7CgogICAgc3RkOjpjb3V0IDw8ICJ0cmFja2VkIEEgKGRlZmF1bHQpXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuIiA7CiAgICB0cmFja2VkPEE+Ojpmb3JfZWFjaF9pbnN0YW5jZSggW10oIEEqIHBhICkgeyBwYS0+Zm9vKCAxLCAneCcgKSA7IH0gKSA7CgogICAgc3RkOjpjb3V0IDw8ICJcbnRyYWNrZWQgQSAobXlfb2JqZWN0cylcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuIiA7CiAgICB0cmFja2VkPEEsbXlfb2JqZWN0cz46OmZvcl9lYWNoX2luc3RhbmNlKCBbXSggQSogcGEgKSB7IHBhLT5mb28oIDIsICd5JyApIDsgfSApIDsKCiAgICBzdGQ6OmNvdXQgPDwgIlxudHJhY2tlZCBBICh0aGVpcl9vYmplY3RzKVxuLS0tLS0tLS0tLS0tLS1cbiIgOwogICAgdHJhY2tlZDxBLHRoZWlyX29iamVjdHM+Ojpmb3JfZWFjaF9pbnN0YW5jZSggW10oIEEqIHBhICkgeyBwYS0+Zm9vKCAzLCAneicgKSA7IH0gKSA7CgogICAgc3RkOjpjb3V0IDw8ICJcbnRyYWNrZWQgQiAobXlfb2JqZWN0cylcbi0tLS0tLS0tLS0tLS0tXG4iIDsKICAgIHRyYWNrZWQ8QixteV9vYmplY3RzPjo6Zm9yX2VhY2hfaW5zdGFuY2UoIFtdKCBCKiBwYiApIHsgcGItPmJhciggImhlbGxvIiApIDsgfSApIDsKfQo=
tracked A (default)
-----------------------
A::foo( 0x9b821e8, 1, x )
tracked A (my_objects)
---------------------
A::foo( 0x9b82230, 2, y )
A::foo( 0x9b8222c, 2, y )
tracked A (their_objects)
--------------
A::foo( 0xbfc3a9b4, 3, z )
A::foo( 0xbfc3a9b0, 3, z )
A::foo( 0xbfc3a9ac, 3, z )
A::foo( 0xbfc3a9a8, 3, z )
tracked B (my_objects)
--------------
B::bar( 0xbfc3a9a4, hello )
B::bar( 0xbfc3a9a0, hello )
B::bar( 0xbfc3a99c, hello )