namespace tuple_utils { // 'callback' /* struct callback { template<std::size_t, class T> void operator()( T&& element ) { // do something } }; tupleForeach( callback(), myTuple ); */ template<class TCallback, class ...TParams> void tupleForeach( TCallback& callback, const std::tuple<TParams...>& tuple ); namespace { template<std::size_t Index, class TCallback, class ...TParams> struct _foreach_ { static void tupleForeach_( TCallback& callback, const std::tuple<TParams...>& tuple ) { // callback'a const std::size_t idx = sizeof...( TParams ) - Index; callback.operator()<idx>( std::get<idx>( tuple ) ); _foreach_<Index - 1, TCallback, TParams...>::tupleForeach_( callback, tuple ); } }; template<class TCallback, class ...TParams> struct _foreach_<0, TCallback, TParams...> { static void tupleForeach_( TCallback& /*callback*/, const std::tuple<TParams...>& /*tuple*/ ) {} }; } // template<class TCallback, class ...TParams> void tupleForeach( TCallback& callback, const std::tuple<TParams...>& tuple ) { _foreach_<sizeof...( TParams ), TCallback, TParams...>::tupleForeach_( callback, tuple ); } } // tuple_utils
struct ForeachCallback { template<std::size_t Index, class T> void operator()( T&& element ) { std::cout << "( " << Index << " : " << element << " ) "; } }; void foo() { auto myTyple = std::make_tuple( 42, 3.14, "boo" ); tuple_utils::tupleForeach( ForeachCallback(), myTyple ); }
// getter' template<class TResult, class TOwner> using TGetter = TResult( TOwner::* )() const; // , getter' template<class TGetterOwner, class ...TParams> class MyGetterContainer { // getter' template<class TResult> using TMyGetter = TGetter<TResult, TGetterOwner>; ..... private: ..... // , getter' ( nullptr) void checkGetters(); // getter' (.. ) std::tuple<TMyGetter<TParams>...> m_getters; }; namespace { // callback, getter' template<class TGetterOwner> struct GetterCheckCallback { // , getter' // 'Index' template<std::size_t Index, class T> void operator()( const TGetter<T, TGetterOwner>& element ) { assert( element != nullptr ); } }; } // template<class TGetterOwner, class ...TParams> void MyGetterContainer<TGetterOwner, TParams...>::checkGetters() { // callback getter' tuple_utils::tupleForeach( GetterCheckCallback<TGetterOwner>(), m_getters ); }
namespace tuple_utils { // ( ) 'callback' 'sourceTuple' /* struct callback { template<std::size_t, class R, class T> R operator()( T&& element ) { // do something } }; mapTuple( callback(), myTuple ); */ template<class TCallback, class TSourceTuple> auto mapTuple( TCallback& callback, const TSourceTuple& sourceTuple ); namespace { template<class TCallback, class TSourceTuple, std::size_t... Indices> auto mapTuple_( TCallback& callback, const TSourceTuple& sourceTuple, std::index_sequence<Indices...> ) { return std::make_tuple( callback.operator()<Indices>( std::get<Indices>( sourceTuple ) )... ); } } // template<class TCallback, class TSourceTuple> auto mapTuple( TCallback& callback, const TSourceTuple& sourceTuple ) { return mapTuple_( callback, sourceTuple, std::make_index_sequence<std::tuple_size<TSourceTuple>::value>() ); } } // tuple_utils
struct MapCallback { template<std::size_t Index, class T> std::string operator()( T&& element ) { std::stringstream ss; ss << "( " << Index << " : " << element << " )"; std::string result; result << ss; return result; } }; void foo() { auto sourceTyple = std::make_tuple( 42, 3.14, "boo" ); auto strTuple = tuple_utils::mapTuple( MapCallback(), sourceTyple ); }
// getter' template<class TResult, class TOwner> using TGetter = TResult( TOwner::* )() const; // , getter' template<class TGetterOwner, class ...TParams> class MyGetterContainer { // getter' template<class TResult> using TMyGetter = TGetter<TResult, TGetterOwner>; ..... protected: ..... // getter' std::tuple<TParams...> getterValues() const; private: ..... // , getter' TGetterOwner& m_getterOwner; // getter' (.. ) std::tuple<TMyGetter<TParams>...> m_getters; }; namespace { // callback, getter' template<class TGetterOwner> struct GetterValuesCallback { public: // GetterValuer( const TGetterOwner& getterOwner ) : m_getterOwner( getterOwner ) { } // , getter'; getter' // 'Index' template<std::size_t Index, class T> T operator()( const TGetter<T, TGetterOwner>& oneGetter ) { return ( m_getterOwner.*oneGetter )(); } private: const TGetterOwner& m_getterOwner; }; } // template<class TGetterOwner, class ...TParams> std::tuple<TParams...> MyGetterContainer<TGetterOwner, TParams...>::getterValues() const { // callback getter' return tuple_utils::mapTuple( GetterValuesCallback<TGetterOwner>( m_getterOwner ), m_getters ); }
namespace tuple_utils { // 'callback', 'tuple' /* struct callback { template<class TResult, class ...TParams> TResult operator()( TParams... ) { // do something } }; callTuple( callback(), myTuple ); */ template<class TCallback, class ...TParams> auto callTuple( TCallback& callback, const std::tuple<TParams...>& tuple ); namespace { template<class TCallback, class TTuple, std::size_t... Indices> auto callTuple_( TCallback& callback, const TTuple& tuple, std::index_sequence<Indices...> ) { return callback( std::get<Indices>( tuple )... ); } } // template<class TCallback, class ...TParams> auto callTuple( TCallback& callback, const std::tuple<TParams...>& tuple ) { return callTuple_( callback, tuple, std::index_sequence_for<TParams...>() ); } } // tuple_utils
bool checkSomething( int a, float b, const std::string& txt ); struct CallCallback { template<class TResult, class ...TParams> TResult operator()( TParams... params ) { return checkSomething( params... ); } }; void foo() { std::tuple<int, float, std::string> paramsTyple = std::make_tuple( 42, 3.14, "boo" ); bool isParamsValid = tuple_utils::callTuple( CallCallback(), paramsTyple ); }
// , getter' template<class TGetterOwner, class ...TParams> class MyGetterContainer { ..... protected: ..... // getter' std::tuple<TParams...> getterValues() const; ..... }; // setter' void- c template<class TOwner, class ...TParams> using TSetter = void( TOwner::* )( TParams... ); // , setter getter' template<class TSetterOwner, class TGetterOwner, class ...TParams> class MySetterCaller : public MyGetterContainer<TGetterOwner, TParams...> { // getter' using TMySetter = TSetter<TSetterOwner, TParams...>; ..... public: ..... // setter getter' void callSetter(); private: ..... // , setter TSetterOwner& m_setterOwner; // setter TMySetter m_setter; }; namespace { // callback, setter' template<class TSetterOwner, class ...TParams> struct CallSetterCallback { public: // GetterPasser( TSetterOwner& setterOwner, TSetter<TSetterOwner, TParams...> setter ) : m_setterOwner( setterOwner ), m_setter( setter ) { } // , setter' void operator()( TParams... params ) { return ( m_setterOwner.*m_setter )( params... ); } private: TSetterOwner& m_setterOwner; TSetter<TSetterOwner, TParams...> m_setter; }; } // template<class TSetterOwner, class TGetterOwner, class ...TParams> void MySetterCaller<TSetterOwner, TGetterOwner, TParams...>::callSetter() { // getter' std::tuple<TParams...> _getterValues = getterValues(); // callback setter' tuple_utils::callTuple( CallSetterCallback( m_setterOwner, m_setter ), _getterValues ); }
// - void- template<class TObject, class TValue> using TMethodHandler = void( TObject::* )( const TValue& ); // , - template<class ...TValues> class MyHandlerContainer { public: // ; - MyHandlerContainer( const std::function<void( const TValues& )>... handlers ); ..... // - template<class TMethodOwner> static MyHandlerContainer<TValues...>* createFrom( TMethodOwner& methodOwner, TMethodHandler<TMethodOwner, TValues>... handlers ); ..... }; namespace { // callback - template<class TMethodOwner> struct CheckCallback { // CheckCallback() : IsValid( true ) { } // - template<std::size_t Index, class TValue> void operator()( const TMethodHandler<TMethodOwner, TValue>& oneMethodHandler ) { if( oneMethodHandler == nullptr ) IsValid = false; } bool IsValid; } // callback - - template<class TMethodOwner> struct FunctorHandlerCallback { public: // FunctorHandlerCallback( TMethodOwner& methodOwner ) : m_methodOwner( methodOwner ) { } // - - template<std::size_t Index, class TValue> std::function<void( const TValue& )> operator()( const TMethodHandler<TMethodOwner, TValue>& oneHandlers ) { return [ this, oneHandlers ]( const TValue& tValue ) { ( m_methodOwner.*oneHandlers )( tValue ); }; } private: TMethodOwner& m_methodOwner; }; // callback 'MyHandlerContainer' - template<class ...TValues> struct CreateCallback { // 'MyHandlerContainer' - auto operator()( std::function<void( const TValues& )>... handlers ) { return new MyHandlerContainer<TValues...>( handlers... ); } }; } // template<class ...TValues> template<class TMethodOwner> MyHandlerContainer<TValues...>* MyHandlerContainer<TValues...>::createFrom( TMethodOwner& methodOwner, TMethodHandler<TMethodOwner, TValues>... handlers ) { // - auto methodsTuple = std::make_tuple( handlers... ); // , CheckCallback checkCallback; tuple_utils::tupleForeach( checkCallback, methodsTuple ); // if( checkCallback.IsValid ) { // (, ) FunctorHandlerCallback<TMethodOwner>* functorHandlerCallback = new FunctorHandlerCallback<TMethodOwner>( methodHolder ); // - auto handlersTuple = tuple_utils::mapTuple( *functorHandlerCallback, methodsTuple ); // - 'MyHandlerContainer' MyHandlerContainer<TValues...>* result = tuple_utils::callTuple( CreateCallback<TValues...>( multiProperty ), handlersTuple ); return result; } // assert( false ); return nullptr; }
namespace tuple_utils { // tuple (tuple ) 'callback' tuple' /* struct callback { template<std::size_t, class R, class T> R operator()( T&& element ) { // do something } }; mapTuple( callback(), myTuple ); */ template<class TCallback, class TSourceTuple> auto mapTuple( TCallback& callback, const TSourceTuple& sourceTuple ); namespace { template<std::size_t Index, class TCallback, class TSourceTuple, std::size_t... Indices> struct _map_ { auto static mapTuple_( TCallback& callback, const TSourceTuple& sourceTuple ) { const std::size_t idx = std::tuple_size<TSourceTuple>::value - Index; return _map_<Index - 1, TCallback, TSourceTuple, Indices..., idx>::mapTuple_( callback, sourceTuple ); } }; template<class TCallback, class TSourceTuple, std::size_t... Indices> struct _map_<0, TCallback, TSourceTuple, Indices...> { auto static mapTuple_( TCallback& callback, const TSourceTuple& sourceTuple ) { return std::make_tuple( callback.operator()<Indices>( std::get<Indices>( sourceTuple ) )... ); } }; } // template<class TCallback, class TSourceTuple> auto mapTuple( TCallback& callback, const TSourceTuple& sourceTuple ) { return _map_<std::tuple_size<TSourceTuple>::value, TCallback, TSourceTuple>::mapTuple_( callback, sourceTuple ); } } // tuple_utils
namespace tuple_utils { // 'callback', tuple /* struct callback { template<class TResult, class ...TParams> TResult operator()( TParams... params ) { // do something } }; callTuple( callback(), myTuple ); */ template<class TCallback, class TResult, class ...TParams> TResult callTuple( TCallback& callback, const std::tuple<TParams...>& tuple ); namespace { template<std::size_t Index, class TCallback, class TResult, class TTuple, class ...TParams> struct _call_ { static TResult callTuple_( TCallback& callback, const TTuple& tuple, TParams... params ) { const std::size_t idx = std::tuple_size<TTuple>::value - Index; return _call_<Index - 1, TCallback, TResult, TTuple, TParams..., typename std::tuple_element<idx, TTuple>::type>::callTuple_( callback, tuple, params..., std::get<idx>( tuple ) ); } }; template<class TCallback, class TResult, class TTuple, class ...TParams> struct _call_<0, TCallback, TResult, TTuple, TParams...> { static TResult callTuple_( TCallback& callback, const TTuple& tuple, TParams... params ) { return callback( params... ); } }; } // template<class TCallback, class TResult, class ...TParams> TResult callTuple( TCallback& callback, const std::tuple<TParams...>& tuple ) { return _call_<sizeof...( TParams ), TCallback, TResult, std::tuple<TParams...>>::callTuple_( callback, tuple ); } } // tuple_utils
Source: https://habr.com/ru/post/318236/
All Articles