#pragma once #include "typedef.h" template struct FN; // voodoo template struct FN { 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...); }; static const unsigned int BUF_SIZE = 32; alignas(8) char buf[BUF_SIZE]; void* data; RET( *invoke )( void*, ARGS... ); void( *destroy )( void* ); void*( *clone )( void*, char* ); template FN(F&& f) { using __stripped = typename __strip_ref::type; if constexpr( sizeof(__stripped) <= BUF_SIZE ) { new (buf) __stripped( f ); data = buf; destroy = pfn( void* d ) { ( (__stripped*)d )->~__stripped(); }; clone = pfn( void* d, char* dst ) -> void* { new (dst) __stripped( *(__stripped*)d ); return dst; }; } else { data = new __stripped( f ); destroy = pfn( void* d ) { delete (__stripped*)d; }; clone = pfn( void* d, char* dst ) -> void* { return new __stripped( *(__stripped*)d ); }; } invoke = pfn( void* d, ARGS... args ) -> RET { return ( *(__stripped*)d )( args... ); }; } FN( I32&& ) : data( 0 ), invoke( 0 ), destroy( 0 ), clone( 0 ) {} FN( U32&& ) : data( 0 ), invoke( 0 ), destroy( 0 ), clone( 0 ) {} FN() : data( 0 ), invoke( 0 ), destroy( 0 ), clone( 0 ) {} FN( const FN& other ) : invoke( other.invoke ), destroy( other.destroy ), clone( other.clone ) { if( !other.data ) { data = 0; return; } data = other.clone( other.data, buf ); } FN& operator=( const FN& other ) { if( this == &other ) return *this; if( destroy && data ) destroy( data ); invoke = other.invoke; destroy = other.destroy; clone = other.clone; data = other.data ? other.clone( other.data, buf ) : 0; return *this; } ~FN() { if( destroy && data ) destroy( data ); } RET operator()( ARGS... args ) const { return invoke( data, args... ); } operator bool() const { return !!invoke; } };