Есть библиотека (service). Клиенты реализуют колбэк-интерфейс передачи данных (handler). Параметры для передачи передаются библиотеке, которая дёргает колбэк-интерфейс.
Хочется такой интерфейс сервиса библиотеки:
service::send(T&&... args);
И такой интерфейс колбэка (реализуется клиентом)
handler::on_send(T&&... args);
| Ничего, кроме конверта в void* не придумал |
|
//////////////////////////////////////////////
// Код библиотеки
struct Params
{
template<typename... Args>
std::tuple< Args... >* Get()
{
return reinterpret_cast< std::tuple< Args... >* >( p );
};
void* p;
};
struct AbstractHandler
{
virtual ~AbstractHandler() {}
virtual void func( Params& ) = 0;
};
template < typename ResultT, typename... Args >
struct Function
{
using type = std::function< ResultT( Args... ) >;
};
template< typename T >
struct HandlerBase : AbstractHandler
{
typename Function< void, Params& >::type userFuncCaller;
template< typename userFuncResultT, typename... userFuncArgs >
HandlerBase( std::function< userFuncResultT( T*, userFuncArgs... )> userFunc )
{
userFuncCaller = [ this, userFunc ]( Params& p ){
std::tuple< userFuncArgs... > args;
if( p.p )
{
args = *p.Get< userFuncArgs... >();
std::apply( [ this, userFunc ]( auto &&... args ) { userFunc( reinterpret_cast< T* >( this ), args... ); }, args );
}
};
}
void func( Params& p ) override
{
userFuncCaller( p );
}
};
struct Caller
{
Caller()
{
handler.reset( new UserHandler() );
}
template< typename... Args >
void CallFunc( Args&&... args )
{
Params params;
params.p = new std::tuple< Args... >( std::move( args... ) );
handler->func( params );
}
std::unique_ptr< AbstractHandler > handler;
};
//////////////////////////////////////////////
// Клиентский код
struct UserHandler : HandlerBase< UserHandler >
{
// необходимость таким образом передавать функцию удручает
UserHandler() : HandlerBase< UserHandler >( std::function< void( UserHandler*, int ) >( &UserHandler::userFunc ) )
{}
void userFunc( int i )
{
BOOST_TEST_MESSAGE( Format( L"IN USER FUNC - %1%"_sv, i ) );
return;
}
};
void main()
{
Caller call;
call.CallFunc( 5 );
}
|
| |
Будут ещё мнения как это сделать?
Спасибо