From 4a8be9d3ad3c3c3405e88c5be608aa5a4c602dae Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Mon, 20 Nov 2017 06:39:04 +0100 Subject: [PATCH] allow registration of member methods --- alib2cli/test-src/cli/CliTest.cpp | 24 +++++++++++ alib2cli/test-src/cli/CliTest.h | 2 + .../src/abstraction/AlgorithmRegistry.hpp | 33 +++++++++++++++ .../src/abstraction/MemberAbstraction.hpp | 40 +++++++++++++++++++ .../abstraction/ValueOperationAbstraction.hpp | 10 +++++ 5 files changed, 109 insertions(+) create mode 100644 alib2common/src/abstraction/MemberAbstraction.hpp diff --git a/alib2cli/test-src/cli/CliTest.cpp b/alib2cli/test-src/cli/CliTest.cpp index caee106204..c848b39da5 100644 --- a/alib2cli/test-src/cli/CliTest.cpp +++ b/alib2cli/test-src/cli/CliTest.cpp @@ -267,3 +267,27 @@ void CliTest::testSetConstruction ( ) { parser = cli::Parser ( cli::Lexer ( "execute $set2 | Print -" ) ); parser.parse ( )->run ( environment ); } + +class Foo { + int m_base; +public: + Foo ( int base ) : m_base ( base ) { + } + + int bar ( int value ) { + return m_base + value; + } + + static Foo make_foo ( int base ) { + return Foo ( base ); + } +}; + +void CliTest::testMember ( ) { + abstraction::AlgorithmRegistry::registerAlgorithm < Foo > ( Foo::make_foo, abstraction::AlgorithmCategories::AlgorithmCategory::DEFAULT, std::array < std::string, 1 > ( ) ); + abstraction::AlgorithmRegistry::registerMethod < Foo > ( & Foo::bar, "bar", std::array < std::string, 1 > ( ) ); + + cli::Environment environment; + cli::Parser parser ( cli::Lexer ( "execute Foo 3 | Foo::bar - 2" ) ); + parser.parse ( )->run ( environment ); +} diff --git a/alib2cli/test-src/cli/CliTest.h b/alib2cli/test-src/cli/CliTest.h index d9f5c7af68..21a3fdd0f5 100644 --- a/alib2cli/test-src/cli/CliTest.h +++ b/alib2cli/test-src/cli/CliTest.h @@ -12,6 +12,7 @@ class CliTest : public CppUnit::TestFixture { CPPUNIT_TEST ( testReferencePassing ); CPPUNIT_TEST ( testConstRvalueReferencePassing ); CPPUNIT_TEST ( testSetConstruction ); + CPPUNIT_TEST ( testMember ); CPPUNIT_TEST_SUITE_END ( ); public: @@ -25,6 +26,7 @@ public: void testReferencePassing ( ); void testConstRvalueReferencePassing ( ); void testSetConstruction ( ); + void testMember ( ); }; #endif // CLI_TEST_H_ diff --git a/alib2common/src/abstraction/AlgorithmRegistry.hpp b/alib2common/src/abstraction/AlgorithmRegistry.hpp index 2e400ab150..8a499839a2 100644 --- a/alib2common/src/abstraction/AlgorithmRegistry.hpp +++ b/alib2common/src/abstraction/AlgorithmRegistry.hpp @@ -31,6 +31,17 @@ class AlgorithmRegistry { virtual std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( ) const = 0; }; + template < class ObjectType, class Return, class ... Params > + class MemberImpl : public Entry { + std::function < Return ( ObjectType *, Params ... ) > m_callback; + + public: + MemberImpl ( std::function < Return ( ObjectType *, Params ... ) > callback ) : m_callback ( callback ) { + } + + virtual std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( ) const override; + }; + template < class Return, class ... Params > class EntryImpl : public Entry { std::function < Return ( Params ... ) > m_callback; @@ -94,6 +105,22 @@ class AlgorithmRegistry { static void registerInternal ( std::string algorithm, AlgorithmCategories::AlgorithmCategory category, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > result, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > params, std::shared_ptr < Entry > value ); public: + template < class Algo, class ObjectType, class ReturnType, class ... ParamTypes > + static void registerMethod ( ReturnType ( ObjectType:: * callback ) ( ParamTypes ... ), std::string methodName, std::array < std::string, sizeof ... ( ParamTypes ) > paramNames ) { + AlgorithmCategories::AlgorithmCategory category = AlgorithmCategories::AlgorithmCategory::DEFAULT; + std::string algorithm = ext::to_string < Algo > ( ) + "::" + methodName; + + ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > params = convertParamTypes < ParamTypes ... > ( paramNames ); + params.insert ( params.begin ( ), convertParamType < ObjectType > ( "object" ) ); + + ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > result = convertReturnType < ReturnType > ( ); + + if ( isRegistered ( algorithm, category, params ) ) + throw exception::CommonException ( "Callback for " + algorithm + " already registered." ); + + registerInternal ( std::move ( algorithm ), category, std::move ( result ), std::move ( params ), std::make_shared < MemberImpl < ObjectType, ReturnType, ParamTypes ... > > ( callback ) ); + } + template < class Algo, class ReturnType, class ... ParamTypes > static void registerAlgorithm ( ReturnType ( * callback ) ( ParamTypes ... ), AlgorithmCategories::AlgorithmCategory category, std::array < std::string, sizeof ... ( ParamTypes ) > paramNames ) { std::string algorithm = ext::to_string < Algo > ( ); @@ -130,11 +157,17 @@ public: } /* namespace abstraction */ +#include <abstraction/MemberAbstraction.hpp> #include <abstraction/AlgorithmAbstraction.hpp> #include <abstraction/WrapperAbstraction.hpp> namespace abstraction { +template < class Object, class Return, class ... Params > +std::shared_ptr < abstraction::OperationAbstraction > AlgorithmRegistry::MemberImpl < Object, Return, Params ... >::getAbstraction ( ) const { + return std::make_shared < abstraction::MemberAbstraction < Object, Return, Params ... > > ( m_callback ); +} + template < class Return, class ... Params > std::shared_ptr < abstraction::OperationAbstraction > AlgorithmRegistry::EntryImpl < Return, Params ... >::getAbstraction ( ) const { return std::make_shared < abstraction::AlgorithmAbstraction < Return, Params ... > > ( m_callback ); diff --git a/alib2common/src/abstraction/MemberAbstraction.hpp b/alib2common/src/abstraction/MemberAbstraction.hpp new file mode 100644 index 0000000000..86e17756cb --- /dev/null +++ b/alib2common/src/abstraction/MemberAbstraction.hpp @@ -0,0 +1,40 @@ +/* + * MemberAbstraction.hpp + * + * Created on: 11. 7. 2017 + * Author: Jan Travnicek + */ + +#ifndef _MEMBER_ABSTRACTION_HPP_ +#define _MEMBER_ABSTRACTION_HPP_ + +#include <abstraction/NaryOperationAbstraction.hpp> +#include <memory> +#include <abstraction/Registry.h> + +namespace abstraction { + +template < class ObjectType, class ReturnType, class ... ParamTypes > +class MemberAbstraction : public NaryOperationAbstraction < ReturnType, ObjectType &, ParamTypes ... > { + std::function < ReturnType ( ObjectType *, ParamTypes ... ) > m_callback; + +public: + MemberAbstraction ( std::function < ReturnType ( ObjectType *, ParamTypes ... ) > callback ) : m_callback ( callback ) { + } + + virtual bool run ( ) override { + if ( ! this->inputsReady ( ) ) + return false; + + if ( this->cached ( ) ) + return true; + + this->member_run_helper ( m_callback, this->m_params, this->m_moves, std::make_index_sequence < sizeof ... ( ParamTypes ) > { } ); + return true; + } + +}; + +} /* namespace abstraction */ + +#endif /* _MEMBER_ABSTRACTION_HPP_ */ diff --git a/alib2common/src/abstraction/ValueOperationAbstraction.hpp b/alib2common/src/abstraction/ValueOperationAbstraction.hpp index a08d007f27..19dde2e605 100644 --- a/alib2common/src/abstraction/ValueOperationAbstraction.hpp +++ b/alib2common/src/abstraction/ValueOperationAbstraction.hpp @@ -31,6 +31,16 @@ protected: mutable ext::variant < void, ReturnType > m_data; public: + template < typename Callable, typename Object, typename ... Ts, size_t ... Indexes > + inline void member_run_helper ( Callable callback, const ext::tuple < Object, Ts ... > & inputs, const std::array < bool, 1 + sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) { + /* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */ + ( void ) inputs; + ( void ) moves; + + if ( ! isReady ( ) ) + m_data = callback ( & std::get < 0 > ( inputs )->getValue ( false ), std::get < Indexes + 1 > ( inputs )->getValue ( std::get < Indexes + 1 > ( moves ) ) ... ); + } + template < typename Callable, typename ... Ts, size_t ... Indexes > inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, const std::array < bool, sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) { /* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */ -- GitLab