#pragma once #include "typedef.h" template struct FN; template struct FN { // voodoo template struct __strip_ref { using type = T; }; template struct __strip_ref { using type = T; }; template struct __strip_ref { using type = T; }; template struct __strip_ref { using type = R(*)(A...); }; template struct __strip_ref { using type = R(*)(A...); }; void* data; U32 size; RET( *invoke )( void*, ARGS... ); void( *destroy )( void* ); void*( *clone )( void* ); template FN( F&& f ) { using __stripped = typename __strip_ref::type; data = new __stripped( static_cast(f) ); size = sizeof( __stripped ); invoke = pfn( void* d, ARGS... args ) -> RET { return ( *(__stripped*)d )( args... ); }; destroy = pfn( void* d ) { delete (__stripped*)d; }; clone = pfn( void* data ) { return (void*)new __stripped( *(__stripped*)data ); }; } template <> FN( int&& ) : data( 0 ), invoke( 0 ), destroy( 0 ) {} FN() : data( 0 ), invoke( 0 ), destroy( 0 ) {} FN( FN&& other ) : data( other.data ), invoke( other.invoke ), destroy( other.destroy ) { other.data = 0; other.invoke = 0; other.destroy = 0; } FN& operator=( FN&& other ) { if( this == &other ) return *this; if( destroy ) destroy( data ); data = other.data; invoke = other.invoke; destroy = other.destroy; other.data = 0; other.invoke = 0; other.destroy = 0; return *this; } FN( const FN& other ) { *this = other; }; FN& operator=( const FN& other ) { if( !other.data ) { data = 0; invoke = 0; destroy = 0; size = 0; return *this; } size = other.size; data = other.clone( other.data ); invoke = other.invoke; destroy = other.destroy; clone = other.clone; return *this; } ~FN() { if( destroy ) destroy( data ); } operator bool() const { return !!invoke; } RET operator()( ARGS... args ) const { return invoke( data, args... ); } };