From 70011a43eb737ee099737a3f8b05bee47701b771 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Mon, 5 Sep 2016 19:07:45 +0200 Subject: [PATCH] unify basic dispatch algorithms --- alib2algo/src/graph/traverse/Bfs.cpp | 8 +- alib2algo/src/graph/traverse/Dfs.cpp | 8 +- alib2common/src/core/multipleDispatch.hpp | 237 ++++----------------- alib2common/test-src/core/DispatchTest.cpp | 2 +- 4 files changed, 45 insertions(+), 210 deletions(-) diff --git a/alib2algo/src/graph/traverse/Bfs.cpp b/alib2algo/src/graph/traverse/Bfs.cpp index a57e332ab9..974e0c7024 100644 --- a/alib2algo/src/graph/traverse/Bfs.cpp +++ b/alib2algo/src/graph/traverse/Bfs.cpp @@ -77,25 +77,25 @@ void Bfs::bfs(const DirectedGraph &graph, const Node &start, Bfs::Function func) bfs_impl(graph, start, func); } -auto BfsDirectedGraph1 = Bfs::SingleDispatch<Bfs, void, const graph::GraphBase &, const Node&, Bfs::Function>::RegistratorWrapper<void, graph::DirectedGraph>(Bfs::bfs); +auto BfsDirectedGraph1 = std::SingleDispatch<Bfs, void, const graph::GraphBase &, const Node&, Bfs::Function>::RegistratorWrapper<void, graph::DirectedGraph>(Bfs::bfs); void Bfs::bfs(const DirectedGraph &graph, const Node &start, Bfs::FunctionExt func) { bfs2_impl(graph, start, func); } -auto BfsDirectedGraph2 = Bfs::SingleDispatch<Bfs, void, const graph::GraphBase &, const Node&, Bfs::FunctionExt>::RegistratorWrapper<void, graph::DirectedGraph>(Bfs::bfs); +auto BfsDirectedGraph2 = std::SingleDispatch<Bfs, void, const graph::GraphBase &, const Node&, Bfs::FunctionExt>::RegistratorWrapper<void, graph::DirectedGraph>(Bfs::bfs); void Bfs::bfs(const UndirectedGraph &graph, const Node &start, Bfs::Function func) { bfs_impl(graph, start, func); } -auto BfsUndirectedGraph1 = Bfs::SingleDispatch<Bfs, void, const graph::GraphBase &, const Node&, Bfs::Function>::RegistratorWrapper<void, graph::UndirectedGraph>(Bfs::bfs); +auto BfsUndirectedGraph1 = std::SingleDispatch<Bfs, void, const graph::GraphBase &, const Node&, Bfs::Function>::RegistratorWrapper<void, graph::UndirectedGraph>(Bfs::bfs); void Bfs::bfs(const UndirectedGraph &graph, const Node &start, Bfs::FunctionExt func) { bfs2_impl(graph, start, func); } -auto BfsUndirectedGraph2 = Bfs::SingleDispatch<Bfs, void, const graph::GraphBase &, const Node&, Bfs::FunctionExt>::RegistratorWrapper<void, graph::UndirectedGraph>(Bfs::bfs); +auto BfsUndirectedGraph2 = std::SingleDispatch<Bfs, void, const graph::GraphBase &, const Node&, Bfs::FunctionExt>::RegistratorWrapper<void, graph::UndirectedGraph>(Bfs::bfs); } // namespace traverse diff --git a/alib2algo/src/graph/traverse/Dfs.cpp b/alib2algo/src/graph/traverse/Dfs.cpp index 0eaa729f9e..50dcfea7a7 100644 --- a/alib2algo/src/graph/traverse/Dfs.cpp +++ b/alib2algo/src/graph/traverse/Dfs.cpp @@ -66,7 +66,7 @@ void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::Function func) dfs_impl(graph, start, func); } -auto DfsDirectedGraph1 = Dfs::SingleDispatch<Dfs, void, const graph::GraphBase &, const Node&, Dfs::Function>::RegistratorWrapper<void, graph::DirectedGraph>(Dfs::dfs); +auto DfsDirectedGraph1 = std::SingleDispatch<Dfs, void, const graph::GraphBase &, const Node&, Dfs::Function>::RegistratorWrapper<void, graph::DirectedGraph>(Dfs::dfs); void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::FunctionExt func) { int time = 0; @@ -74,13 +74,13 @@ void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::FunctionExt fu dfs2_impl(graph, start, start, visited, time, func); } -auto DfsDirectedGraph2 = Dfs::SingleDispatch<Dfs, void, const graph::GraphBase &, const Node&, Dfs::FunctionExt>::RegistratorWrapper<void, graph::DirectedGraph>(Dfs::dfs); +auto DfsDirectedGraph2 = std::SingleDispatch<Dfs, void, const graph::GraphBase &, const Node&, Dfs::FunctionExt>::RegistratorWrapper<void, graph::DirectedGraph>(Dfs::dfs); void Dfs::dfs(const UndirectedGraph &graph, const Node &start, Dfs::Function func) { dfs_impl(graph, start, func); } -auto DfsUndirectedGraph1 = Dfs::SingleDispatch<Dfs, void, const graph::GraphBase &, const Node&, Dfs::Function>::RegistratorWrapper<void, graph::UndirectedGraph>(Dfs::dfs); +auto DfsUndirectedGraph1 = std::SingleDispatch<Dfs, void, const graph::GraphBase &, const Node&, Dfs::Function>::RegistratorWrapper<void, graph::UndirectedGraph>(Dfs::dfs); void Dfs::dfs(const UndirectedGraph &graph, const Node &start, Dfs::FunctionExt func) { int time = 0; @@ -88,7 +88,7 @@ void Dfs::dfs(const UndirectedGraph &graph, const Node &start, Dfs::FunctionExt dfs2_impl(graph, start, start, visited, time, func); } -auto DfsUndirectedGraph2 = Dfs::SingleDispatch<Dfs, void, const graph::GraphBase &, const Node&, Dfs::FunctionExt>::RegistratorWrapper<void, graph::UndirectedGraph>(Dfs::dfs); +auto DfsUndirectedGraph2 = std::SingleDispatch<Dfs, void, const graph::GraphBase &, const Node&, Dfs::FunctionExt>::RegistratorWrapper<void, graph::UndirectedGraph>(Dfs::dfs); } // namespace traverse diff --git a/alib2common/src/core/multipleDispatch.hpp b/alib2common/src/core/multipleDispatch.hpp index 26e1ee366f..789d7d63d4 100644 --- a/alib2common/src/core/multipleDispatch.hpp +++ b/alib2common/src/core/multipleDispatch.hpp @@ -13,125 +13,86 @@ #include <map> #include <iostream> #include <type_traits> +#include <sstream> #include "../cast/CastApi.hpp" #include "../exception/CommonException.h" namespace std { -template < class Algorithm, class ReturnType, class FirstParameterType, class ... StaticParamTypes > -class SingleDispatch { +template < class Algorithm, class ReturnType, class ... Params > +class MultipleDispatch; + +template < class Algorithm, class ReturnType, class ... FrontStaticParamTypes, class ... DispatchedParameterTypes, class ... BackStaticParamTypes > +class MultipleDispatch < Algorithm, ReturnType, tuple < FrontStaticParamTypes ... >, tuple < DispatchedParameterTypes ... >, tuple < BackStaticParamTypes ... > > { public: class RegistratorWrapperBase { public: - virtual ReturnType eval ( FirstParameterType &&, StaticParamTypes ... ) = 0; + virtual ReturnType eval ( FrontStaticParamTypes ..., DispatchedParameterTypes && ..., BackStaticParamTypes ... ) = 0; }; private: - std::map < std::type_index, RegistratorWrapperBase * > registeredFunctions; + map < typename TupleBuilder < type_index, sizeof ... ( DispatchedParameterTypes ) >::type, RegistratorWrapperBase * > registeredFunctions; - static SingleDispatch < Algorithm, ReturnType, FirstParameterType, StaticParamTypes ... > & getInstance ( ) { - static SingleDispatch < Algorithm, ReturnType, FirstParameterType, StaticParamTypes ... > res; + static MultipleDispatch < Algorithm, ReturnType, tuple < FrontStaticParamTypes ... >, tuple < DispatchedParameterTypes ... >, tuple < BackStaticParamTypes ... > > & getInstance ( ) { + static MultipleDispatch < Algorithm, ReturnType, tuple < FrontStaticParamTypes ... >, tuple < DispatchedParameterTypes ... >, tuple < BackStaticParamTypes ... > > res; return res; } public: - template < class RealReturnType, class RealFirstParameterTypeBase > + template < class RealReturnType, class ... RealParameterTypeBases > class RegistratorWrapper : public RegistratorWrapperBase { - typedef typename match_cv_ref < FirstParameterType, RealFirstParameterTypeBase >::type RealFirstParameterType; - - std::function < RealReturnType ( RealFirstParameterType &&, StaticParamTypes ... ) > callback; + function < RealReturnType ( FrontStaticParamTypes ..., typename match_cv_ref < DispatchedParameterTypes, RealParameterTypeBases >::type && ..., BackStaticParamTypes ... ) > callback; public: - ReturnType eval ( FirstParameterType && first, StaticParamTypes ... res ) { - return ReturnType ( callback ( forward < RealFirstParameterType > ( static_cast < RealFirstParameterType && > ( first ) ), res ... ) ); + ReturnType eval ( FrontStaticParamTypes ... front, DispatchedParameterTypes && ... dispatched, BackStaticParamTypes ... back ) { + return ReturnType ( callback ( front ..., forward < typename match_cv_ref < DispatchedParameterTypes, RealParameterTypeBases >::type > ( static_cast < typename match_cv_ref < DispatchedParameterTypes, RealParameterTypeBases >::type && > ( dispatched ) ) ..., back ... ) ); } - RegistratorWrapper ( RealReturnType ( * callback ) ( RealFirstParameterType &&, StaticParamTypes ... ) ) : callback ( callback ) { - if ( !getInstance ( ).registeredFunctions.insert ( std::make_pair ( std::type_index ( typeid ( RealFirstParameterType ) ), this ) ).second ) { - std::string firstType = std::cstringToString ( std::type_name < RealFirstParameterType > ( ) ); + RegistratorWrapper ( RealReturnType ( * callback ) ( FrontStaticParamTypes ..., typename match_cv_ref < DispatchedParameterTypes, RealParameterTypeBases >::type && ..., BackStaticParamTypes ... ) ) : callback ( callback ) { + if ( !getInstance ( ).registeredFunctions.insert ( make_pair ( make_tuple ( type_index ( typeid ( typename match_cv_ref < DispatchedParameterTypes, RealParameterTypeBases >::type ) ) ... ), this ) ).second ) { + stringstream ss; + ( void ) initializer_list < int > { ( ss << cstringToString ( type_name < typename match_cv_ref < DispatchedParameterTypes, RealParameterTypeBases >::type > ( ) ), 0 ) ... }; - std::string classType = std::cstringToString ( std::type_name < Algorithm > ( ) ); + string classType = cstringToString ( type_name < Algorithm > ( ) ); - throw::exception::CommonException ( "Callback for " + firstType + " already registered on " + classType + "." ); + throw::exception::CommonException ( "Callback for " + ss.str ( ) + " already registered on " + classType + "." ); } } }; - static ReturnType dispatch ( FirstParameterType && first, StaticParamTypes ... res ) { - typename std::map < std::type_index, RegistratorWrapperBase * >::iterator callback = getInstance ( ).registeredFunctions.find ( std::type_index ( typeid ( first ) ) ); + static ReturnType dispatch ( FrontStaticParamTypes ... front, DispatchedParameterTypes && ... dispatched, BackStaticParamTypes ... back ) { + typename map < typename TupleBuilder < type_index, sizeof ... ( DispatchedParameterTypes ) >::type, RegistratorWrapperBase * >::iterator callback = getInstance ( ).registeredFunctions.find ( make_tuple ( type_index ( typeid ( dispatched ) ) ... ) ); if ( callback == getInstance ( ).registeredFunctions.end ( ) ) { - std::string firstType = std::cstringToString ( std::type_name ( typeid ( first ) ) ); + stringstream ss; + ( void ) initializer_list < int > { ( ss << cstringToString ( type_name ( typeid ( dispatched ) ) ), 0 ) ... }; - std::string classType = std::cstringToString ( std::type_name < Algorithm > ( ) ); + string classType = cstringToString ( type_name < Algorithm > ( ) ); - throw::exception::CommonException ( "Callback for " + firstType + " not registered on " + classType + "." ); + throw::exception::CommonException ( "Callback for " + ss.str ( ) + " not registered on " + classType + "." ); } - return callback->second->eval ( forward < FirstParameterType > ( first ), res ... ); + return callback->second->eval ( front ..., forward < DispatchedParameterTypes > ( dispatched ) ..., back ... ); } }; -template < class Algorithm, class ReturnType, class StaticParamType, class FirstParameterType > -class SingleDispatchFirstStaticParam { -public: - class RegistratorWrapperBase { - public: - virtual ReturnType eval ( StaticParamType, FirstParameterType && ) = 0; - }; - -private: - std::map < std::type_index, RegistratorWrapperBase * > registeredFunctions; - - static SingleDispatchFirstStaticParam < Algorithm, ReturnType, StaticParamType, FirstParameterType > & getInstance ( ) { - static SingleDispatchFirstStaticParam < Algorithm, ReturnType, StaticParamType, FirstParameterType > res; - - return res; - } - -public: - template < class RealReturnType, class RealFirstParameterTypeBase > - class RegistratorWrapper : public RegistratorWrapperBase { - typedef typename match_cv_ref < FirstParameterType, RealFirstParameterTypeBase >::type RealFirstParameterType; - - std::function < RealReturnType ( StaticParamType, RealFirstParameterType && ) > callback; - - public: - ReturnType eval ( StaticParamType res, FirstParameterType && first ) { - return ReturnType ( callback ( res, forward < RealFirstParameterType > ( static_cast < RealFirstParameterType && > ( first ) ) ) ); - } - - RegistratorWrapper ( RealReturnType ( * callback ) ( StaticParamType, RealFirstParameterType && ) ) : callback ( callback ) { - if ( !getInstance ( ).registeredFunctions.insert ( std::make_pair ( std::type_index ( typeid ( RealFirstParameterType ) ), this ) ).second ) { - std::string firstType = std::cstringToString ( std::type_name < RealFirstParameterType > ( ) ); - - std::string classType = std::cstringToString ( std::type_name < Algorithm > ( ) ); - - throw::exception::CommonException ( "Callback for " + firstType + " already registered on " + classType + "." ); - } - } - - }; - - static ReturnType dispatch ( StaticParamType res, FirstParameterType && first ) { - typename std::map < std::type_index, RegistratorWrapperBase * >::iterator callback = getInstance ( ).registeredFunctions.find ( std::type_index ( typeid ( first ) ) ); - - if ( callback == getInstance ( ).registeredFunctions.end ( ) ) { - std::string firstType = std::cstringToString ( std::type_name ( typeid ( first ) ) ); +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - std::string classType = std::cstringToString ( std::type_name < Algorithm > ( ) ); +template < class Algorithm, class ReturnType, class FirstParameterType, class ... StaticParamTypes > +using SingleDispatch = MultipleDispatch < Algorithm, ReturnType, tuple < >, tuple < FirstParameterType >, tuple < StaticParamTypes ... > >; - throw::exception::CommonException ( "Callback for " + firstType + " not registered on " + classType + "." ); - } +template < class Algorithm, class ReturnType, class StaticParamType, class FirstParameterType > +using SingleDispatchFirstStaticParam = MultipleDispatch < Algorithm, ReturnType, tuple < StaticParamType >, tuple < FirstParameterType >, tuple < > >; - return callback->second->eval ( res, forward < FirstParameterType > ( first ) ); - } +template < class Algorithm, class ReturnType, class FirstParameterType, class SecondParameterType, class ... StaticParamTypes > +using DoubleDispatch = MultipleDispatch < Algorithm, ReturnType, tuple < >, tuple < FirstParameterType, SecondParameterType >, tuple < StaticParamTypes ... > >; -}; +template < class Algorithm, class ReturnType, class StaticParamType, class FirstParameterType, class SecondParameterType > +using DoubleDispatchFirstStaticParam = MultipleDispatch < Algorithm, ReturnType, tuple < StaticParamType >, tuple < FirstParameterType, SecondParameterType >, tuple < > >; // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -217,132 +178,6 @@ public: }; -// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -template < class Algorithm, class ReturnType, class FirstParameterType, class SecondParameterType, class ... StaticParamType > -class DoubleDispatch { -public: - class RegistratorWrapperBase { - public: - virtual ReturnType eval ( FirstParameterType &&, SecondParameterType &&, StaticParamType ... ) = 0; - }; - -private: - std::map < std::pair < std::type_index, std::type_index >, RegistratorWrapperBase * > registeredFunctions; - - static DoubleDispatch < Algorithm, ReturnType, FirstParameterType, SecondParameterType, StaticParamType ... > & getInstance ( ) { - static DoubleDispatch < Algorithm, ReturnType, FirstParameterType, SecondParameterType, StaticParamType ... > res; - - return res; - } - -public: - template < class RealReturnType, class RealFirstParameterTypeBase, class RealSecondParameterTypeBase > - class RegistratorWrapper : public RegistratorWrapperBase { - typedef typename match_cv_ref < FirstParameterType, RealFirstParameterTypeBase >::type RealFirstParameterType; - typedef typename match_cv_ref < SecondParameterType, RealSecondParameterTypeBase >::type RealSecondParameterType; - - std::function < RealReturnType ( const RealFirstParameterType &, const RealSecondParameterType &, StaticParamType ... ) > callback; - - public: - ReturnType eval ( FirstParameterType && first, SecondParameterType && second, StaticParamType ... res ) { - return ReturnType ( callback ( forward < RealFirstParameterType > ( ( RealFirstParameterType && ) first ), forward < RealSecondParameterType > ( ( RealSecondParameterType && ) second ), res ... ) ); - } - - RegistratorWrapper ( RealReturnType ( * callback ) ( const RealFirstParameterType &, const RealSecondParameterType &, StaticParamType ... ) ) : callback ( callback ) { - if ( !getInstance ( ).registeredFunctions.insert ( std::make_pair ( std::make_pair ( std::type_index ( typeid ( RealFirstParameterType ) ), std::type_index ( typeid ( RealSecondParameterType ) ) ), this ) ).second ) { - std::string firstType = std::cstringToString ( std::type_name < RealFirstParameterType > ( ) ); - - std::string secondType = std::cstringToString ( std::type_name < RealSecondParameterType > ( ) ); - - std::string classType = std::cstringToString ( std::type_name < Algorithm > ( ) ); - - throw::exception::CommonException ( "Callback for (" + firstType + ", " + secondType + ") already registered on " + classType + "." ); - } - } - - }; - - static ReturnType dispatch ( FirstParameterType && first, SecondParameterType && second, StaticParamType ... res ) { - typename std::map < std::pair < std::type_index, std::type_index >, RegistratorWrapperBase * >::iterator callback = getInstance ( ).registeredFunctions.find ( std::make_pair ( std::type_index ( typeid ( first ) ), std::type_index ( typeid ( second ) ) ) ); - - if ( callback == getInstance ( ).registeredFunctions.end ( ) ) { - std::string firstType = std::cstringToString ( std::type_name ( typeid ( first ) ) ); - - std::string secondType = std::cstringToString ( std::type_name ( typeid ( second ) ) ); - - std::string classType = std::cstringToString ( std::type_name < Algorithm > ( ) ); - - throw::exception::CommonException ( "Callback for (" + firstType + ", " + secondType + ") not registered on " + classType + "." ); - } - - return callback->second->eval ( forward < FirstParameterType > ( first ), forward < SecondParameterType > ( second ), res ... ); - } - -}; - -template < class Algorithm, class ReturnType, class StaticParamType, class FirstParameterType, class SecondParameterType > -class DoubleDispatchFirstStaticParam { -public: - class RegistratorWrapperBase { - public: - virtual ReturnType eval ( StaticParamType, FirstParameterType &&, SecondParameterType && ) = 0; - }; - -private: - std::map < std::pair < std::type_index, std::type_index >, RegistratorWrapperBase * > registeredFunctions; - - static DoubleDispatchFirstStaticParam < Algorithm, ReturnType, StaticParamType, FirstParameterType, SecondParameterType > & getInstance ( ) { - static DoubleDispatchFirstStaticParam < Algorithm, ReturnType, StaticParamType, FirstParameterType, SecondParameterType > res; - - return res; - } - -public: - template < class RealReturnType, class RealFirstParameterTypeBase, class RealSecondParameterTypeBase > - class RegistratorWrapper : public RegistratorWrapperBase { - typedef typename match_cv_ref < FirstParameterType, RealFirstParameterTypeBase >::type RealFirstParameterType; - typedef typename match_cv_ref < SecondParameterType, RealSecondParameterTypeBase >::type RealSecondParameterType; - - std::function < RealReturnType ( StaticParamType, RealFirstParameterType &&, RealSecondParameterType && ) > callback; - - public: - ReturnType eval ( StaticParamType res, FirstParameterType && first, SecondParameterType && second ) { - return ReturnType ( callback ( res, forward < RealFirstParameterType > ( static_cast < RealFirstParameterType && > ( first ) ), forward < SecondParameterType > ( static_cast < SecondParameterType && > ( second ) ) ) ); - } - - RegistratorWrapper ( RealReturnType ( * callback ) ( StaticParamType, RealFirstParameterType &&, RealSecondParameterType && ) ) : callback ( callback ) { - if ( !getInstance ( ).registeredFunctions.insert ( std::make_pair ( std::make_pair ( std::type_index ( typeid ( RealFirstParameterType ) ), std::type_index ( typeid ( RealSecondParameterType ) ) ), this ) ).second ) { - std::string firstType = std::cstringToString ( std::type_name < RealFirstParameterType > ( ) ); - - std::string secondType = std::cstringToString ( std::type_name < RealSecondParameterType > ( ) ); - - std::string classType = std::cstringToString ( std::type_name < Algorithm > ( ) ); - - throw::exception::CommonException ( "Callback for (" + firstType + ", " + secondType + ") already registered on " + classType + "." ); - } - } - - }; - - static ReturnType dispatch ( StaticParamType res, FirstParameterType && first, SecondParameterType && second ) { - typename std::map < std::pair < std::type_index, std::type_index >, RegistratorWrapperBase * >::iterator callback = getInstance ( ).registeredFunctions.find ( std::make_pair ( std::type_index ( typeid ( first ) ), std::type_index ( typeid ( second ) ) ) ); - - if ( callback == getInstance ( ).registeredFunctions.end ( ) ) { - std::string firstType = std::cstringToString ( std::type_name ( typeid ( first ) ) ); - - std::string secondType = std::cstringToString ( std::type_name ( typeid ( second ) ) ); - - std::string classType = std::cstringToString ( std::type_name < Algorithm > ( ) ); - - throw::exception::CommonException ( "Callback for (" + firstType + ", " + secondType + ") not registered on " + classType + "." ); - } - - return callback->second->eval ( res, forward < FirstParameterType > ( first ), forward < SecondParameterType > ( second ) ); - } - -}; - } /* namespace std */ #endif /* MULTIPLE_DISPATCH_H_ */ diff --git a/alib2common/test-src/core/DispatchTest.cpp b/alib2common/test-src/core/DispatchTest.cpp index 1c07302c13..9db314aec7 100644 --- a/alib2common/test-src/core/DispatchTest.cpp +++ b/alib2common/test-src/core/DispatchTest.cpp @@ -178,7 +178,7 @@ public: // ------------------------------------------------------------------------------------------------------------------------------------------------------- -class TmpVisitor : public std::SingleDispatch < TmpVisitor, int, const TmpBase & > { +class TmpVisitor : public std::MultipleDispatch < TmpVisitor, int, std::tuple < >, std::tuple < const TmpBase & >, std::tuple < > > { public: static int eval ( const Tmp2 & first ) { std::cout << first << std::endl; -- GitLab