#include <tuple>
#include <type_traits>
template< class T, class U = typename std::remove_cv< typename std::remove_reference< T >::type >::type >
struct remove_const_and_reference : remove_const_and_reference< U >
{
};
template< class T >
struct remove_const_and_reference< T, T >
{
typedef T type;
};
class A
{
public:
template< class Ret, class... A >
void Call( Ret f( A... ) ) { CallCore( f ); }
template< class Ret, class Obj, class... A >
void Call( Ret( Obj::*f )( A...) ) { CallCore( f ); }
private:
template< class Ret, class... A >
void CallCore( Ret f( A... ) )
{
using tuple_t = std::tuple< typename remove_const_and_reference< A >::type... >;
}
template< class Ret, class Obj, class... A >
void CallCore( Ret( Obj::*f )( A...) )
{
using tuple_t = std::tuple< typename remove_const_and_reference< A >::type... >;
}
};
template< class T, class... A >
T* New( A&&... args )
{
return new T( std::forward< A >( args )... );
}
class B
{
public:
template< class T, class... A >
void RegisterConstructor()
{
a.Call< T* >( New< T, A... > );
}
template< class Fun >
void Register( Fun f )
{
a.Call( f );
}
private:
A a;
};
struct Foo
{
Foo(){}
~Foo(){}
void FunA( int ){}
};
void FunB( int ){}
int main()
{
B b;
b.Register( FunB );
b.Register( &Foo::FunA );
b.RegisterConstructor< Foo >();
}
I2luY2x1ZGUgPHR1cGxlPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+Cgp0ZW1wbGF0ZTwgY2xhc3MgVCwgY2xhc3MgVSA9IHR5cGVuYW1lIHN0ZDo6cmVtb3ZlX2N2PCB0eXBlbmFtZSBzdGQ6OnJlbW92ZV9yZWZlcmVuY2U8IFQgPjo6dHlwZSA+Ojp0eXBlID4Kc3RydWN0IHJlbW92ZV9jb25zdF9hbmRfcmVmZXJlbmNlIDogcmVtb3ZlX2NvbnN0X2FuZF9yZWZlcmVuY2U8IFUgPgp7Cn07Cgp0ZW1wbGF0ZTwgY2xhc3MgVCA+CnN0cnVjdCByZW1vdmVfY29uc3RfYW5kX3JlZmVyZW5jZTwgVCwgVCA+CnsKICB0eXBlZGVmIFQgdHlwZTsKfTsKCmNsYXNzIEEKewpwdWJsaWM6CiAgdGVtcGxhdGU8IGNsYXNzIFJldCwgY2xhc3MuLi4gQSA+CiAgdm9pZCBDYWxsKCBSZXQgZiggQS4uLiApICkgeyBDYWxsQ29yZSggZiApOyB9CiAgCiAgdGVtcGxhdGU8IGNsYXNzIFJldCwgY2xhc3MgT2JqLCBjbGFzcy4uLiBBID4KICB2b2lkIENhbGwoIFJldCggT2JqOjoqZiApKCBBLi4uKSApIHsgQ2FsbENvcmUoIGYgKTsgfQoKcHJpdmF0ZToKICB0ZW1wbGF0ZTwgY2xhc3MgUmV0LCBjbGFzcy4uLiBBID4KICB2b2lkIENhbGxDb3JlKCBSZXQgZiggQS4uLiApICkKICB7CiAgICB1c2luZyB0dXBsZV90ID0gc3RkOjp0dXBsZTwgdHlwZW5hbWUgcmVtb3ZlX2NvbnN0X2FuZF9yZWZlcmVuY2U8IEEgPjo6dHlwZS4uLiA+OwogIH0KICAKICB0ZW1wbGF0ZTwgY2xhc3MgUmV0LCBjbGFzcyBPYmosIGNsYXNzLi4uIEEgPgogIHZvaWQgQ2FsbENvcmUoIFJldCggT2JqOjoqZiApKCBBLi4uKSApCiAgewogICAgdXNpbmcgdHVwbGVfdCA9IHN0ZDo6dHVwbGU8IHR5cGVuYW1lIHJlbW92ZV9jb25zdF9hbmRfcmVmZXJlbmNlPCBBID46OnR5cGUuLi4gPjsKICB9Cn07Cgp0ZW1wbGF0ZTwgY2xhc3MgVCwgY2xhc3MuLi4gQSA+ClQqIE5ldyggQSYmLi4uIGFyZ3MgKQp7CiAgcmV0dXJuIG5ldyBUKCBzdGQ6OmZvcndhcmQ8IEEgPiggYXJncyApLi4uICk7Cn0KCmNsYXNzIEIKewpwdWJsaWM6CiAgdGVtcGxhdGU8IGNsYXNzIFQsIGNsYXNzLi4uIEEgPgogIHZvaWQgUmVnaXN0ZXJDb25zdHJ1Y3RvcigpCiAgewogICAgYS5DYWxsPCBUKiA+KCBOZXc8IFQsIEEuLi4gPiApOwogIH0KCiAgdGVtcGxhdGU8IGNsYXNzIEZ1biA+CiAgdm9pZCBSZWdpc3RlciggRnVuIGYgKQogIHsKICAgIGEuQ2FsbCggZiApOwogIH0KCnByaXZhdGU6CiAgQSBhOwp9OwoKc3RydWN0IEZvbwp7CiAgRm9vKCl7fQogIH5Gb28oKXt9CiAgdm9pZCBGdW5BKCBpbnQgKXt9Cn07Cgp2b2lkIEZ1bkIoIGludCApe30KCmludCBtYWluKCkKewogIEIgYjsKICBiLlJlZ2lzdGVyKCBGdW5CICk7CiAgYi5SZWdpc3RlciggJkZvbzo6RnVuQSApOwogIGIuUmVnaXN0ZXJDb25zdHJ1Y3RvcjwgRm9vID4oKTsKfQ==