beliebige anzahl argumente weiterleiten mit type erasure
-
hi,
folgender code:
#include <utility> #include <cmath> #include <memory> #include <type_traits> #include <functional> #include <map> #include <initializer_list> #include <iostream> using arg_t = double; struct callable_t { virtual ~callable_t() = default; virtual arg_t invoke( arg_t const* args ) const = 0; }; template< typename T > class one_arg_t : public callable_t { T m_obj; public: template< typename... args_t > one_arg_t( args_t&&... args ) : m_obj( std::forward< args_t >( args )... ) { } virtual arg_t invoke( arg_t const* args ) const override { return m_obj( args[0] ); } }; template< typename T > auto make_one_arg( T&& obj ) { return std::move( std::make_unique< one_arg_t< std::decay_t< T > > >( std::forward< T >( obj ) ) ); } template< typename T > class two_args_t : public callable_t { T m_obj; public: template< typename... args_t > two_args_t( args_t&&... args ) : m_obj( std::forward< args_t >( args )... ) { } virtual arg_t invoke( arg_t const* args ) const override { return m_obj( args[0], args[1] ); } }; template< typename T > auto make_two_args( T&& obj ) { return std::move( std::make_unique< two_args_t< std::decay_t< T > > >( std::forward< T >( obj ) ) ); } class callables_t { std::map< std::size_t, std::unique_ptr< callable_t > > m_callables; public: template< typename T, typename U > void insert( T&& k, U&& v ) { m_callables.insert( decltype( m_callables )::value_type{ std::forward< T >( k ), std::forward< U >( v ) } ); } arg_t invoke( std::size_t n, arg_t const* args ) const { const auto finding = m_callables.find( n ); if( finding == m_callables.end() ) { throw std::logic_error{ "invalid number of arguments" }; } return finding->second->invoke( args ); } }; int main() { callables_t callables; callables.insert( 1, make_one_arg( static_cast< arg_t( * )( arg_t )>( &std::sin ) ) ); callables.insert( 2, make_two_args( static_cast< arg_t( * )( arg_t, arg_t )>( &std::atan2 ) ) ); const std::array< arg_t, 2 > args{ 3.14159265 / 2, args[ 0 ] }; std::cout << callables.invoke( 1, args.data() ) << '\n'; std::cout << callables.invoke( 2, args.data() ) << '\n'; }ich benutze hier
one_arg_tundtwo_args_tum einen pointer auf argumente 'zu entpacken'. faellt euch eine moeglichkeit ein, wie ich das so abaendern kann, dass ich nur noch die anzahl an parametern als template-argument uebergeben kann, so dass danach der pointer automatisch 'extrahiert' wird, wie oben zu sehen in z.b. zeile 53?danke im voraus, lg