I have following Event class, inside of which there is wrapper to register some callable (lambda, std::function, etc) as callback:
#include <boost/type_traits/function_traits.hpp>
template< typename ...Args >
class Callback
{
public:
virtual void OnEvent( const Args&... args ) = 0;
virtual void OnEvent( const EmitContext&, const Args&... args )
{
OnEvent( args... );
}
};
template< typename ...Args >
class Event
{
template< typename Callable >
class CallbackImpl: public Callback< Args... >
{
public:
CallbackImpl( Callable&& func ) : mFunc( func )
{
}
void OnEvent( const Args&... args ) override
{
Call( mFunc, args... );
}
void OnEvent( const EmitContext& emit_context, const Args&... args ) override
{
if constexpr( boost::function_traits< std::remove_pointer < Function > >::arity && std::is_same_v< boost::function_traits< std::remove_pointer< Function > >::arg1_type, EmitContext > )
Call( mFunc, emit_context, args... );
else
OnEvent( args... );
}
private:
using Function = std::remove_reference_t<Callable >;
Function mFunc;
};
template < typename Callable >
void RegisterCallbackFunction( Callable&& func )
{
mCallback = std::make_shared< CallbackImpl< Callable > >( std::forward< Callable >( func ) );
}
void Emit( const Args...& args )
{
EmitContext ctx;
if( mCallback )
mCallback->OnEvent( ctx, args... );
}
private:
std::shared_ptr< Callback< Args... > > mCallback;
};
Callable can accept N first arguments from Args, where 0 <= N <= sizeof( Args... ), Call function deducts appropriate invoke.
Now I need to add variant, where Callable can accept either N arguments as before or some EmitContext structure and N arguments after it.
I'm trying to get arity and 1st argument type (if there is) using boost::function traits, but I get compilation errors:
error: implicit instantiation of undefined template 'boost::detail::function_traits_helper<(lambda at collection_event_manager.cpp:71:57) *>'
public boost::detail::function_traits_helper<typename boost::add_pointer<Function>::type>
error: incomplete definition of type 'boost::function_traits<(lambda at collection_event_manager.cpp:71:57)>'
What am I doing wrong? I've also tried to use it without std::remove_pointer and with std::remove_pointer_t with no avail.