Skip to content
Snippets Groups Projects
Commit 70011a43 authored by Jan Trávníček's avatar Jan Trávníček
Browse files

unify basic dispatch algorithms

parent 1e624f4d
No related branches found
No related tags found
No related merge requests found
...@@ -77,25 +77,25 @@ void Bfs::bfs(const DirectedGraph &graph, const Node &start, Bfs::Function func) ...@@ -77,25 +77,25 @@ void Bfs::bfs(const DirectedGraph &graph, const Node &start, Bfs::Function func)
bfs_impl(graph, start, 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) { void Bfs::bfs(const DirectedGraph &graph, const Node &start, Bfs::FunctionExt func) {
bfs2_impl(graph, start, 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) { void Bfs::bfs(const UndirectedGraph &graph, const Node &start, Bfs::Function func) {
bfs_impl(graph, start, 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) { void Bfs::bfs(const UndirectedGraph &graph, const Node &start, Bfs::FunctionExt func) {
bfs2_impl(graph, start, 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 } // namespace traverse
   
......
...@@ -66,7 +66,7 @@ void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::Function func) ...@@ -66,7 +66,7 @@ void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::Function func)
dfs_impl(graph, start, 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) { void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::FunctionExt func) {
int time = 0; int time = 0;
...@@ -74,13 +74,13 @@ void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::FunctionExt fu ...@@ -74,13 +74,13 @@ void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::FunctionExt fu
dfs2_impl(graph, start, start, visited, time, func); 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) { void Dfs::dfs(const UndirectedGraph &graph, const Node &start, Dfs::Function func) {
dfs_impl(graph, start, 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) { void Dfs::dfs(const UndirectedGraph &graph, const Node &start, Dfs::FunctionExt func) {
int time = 0; int time = 0;
...@@ -88,7 +88,7 @@ void Dfs::dfs(const UndirectedGraph &graph, const Node &start, Dfs::FunctionExt ...@@ -88,7 +88,7 @@ void Dfs::dfs(const UndirectedGraph &graph, const Node &start, Dfs::FunctionExt
dfs2_impl(graph, start, start, visited, time, func); 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 } // namespace traverse
   
......
...@@ -13,125 +13,86 @@ ...@@ -13,125 +13,86 @@
#include <map> #include <map>
#include <iostream> #include <iostream>
#include <type_traits> #include <type_traits>
#include <sstream>
   
#include "../cast/CastApi.hpp" #include "../cast/CastApi.hpp"
#include "../exception/CommonException.h" #include "../exception/CommonException.h"
   
namespace std { namespace std {
   
template < class Algorithm, class ReturnType, class FirstParameterType, class ... StaticParamTypes > template < class Algorithm, class ReturnType, class ... Params >
class SingleDispatch { class MultipleDispatch;
template < class Algorithm, class ReturnType, class ... FrontStaticParamTypes, class ... DispatchedParameterTypes, class ... BackStaticParamTypes >
class MultipleDispatch < Algorithm, ReturnType, tuple < FrontStaticParamTypes ... >, tuple < DispatchedParameterTypes ... >, tuple < BackStaticParamTypes ... > > {
public: public:
class RegistratorWrapperBase { class RegistratorWrapperBase {
public: public:
virtual ReturnType eval ( FirstParameterType &&, StaticParamTypes ... ) = 0; virtual ReturnType eval ( FrontStaticParamTypes ..., DispatchedParameterTypes && ..., BackStaticParamTypes ... ) = 0;
}; };
   
private: 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 MultipleDispatch < Algorithm, ReturnType, tuple < FrontStaticParamTypes ... >, tuple < DispatchedParameterTypes ... >, tuple < BackStaticParamTypes ... > > & getInstance ( ) {
static SingleDispatch < Algorithm, ReturnType, FirstParameterType, StaticParamTypes ... > res; static MultipleDispatch < Algorithm, ReturnType, tuple < FrontStaticParamTypes ... >, tuple < DispatchedParameterTypes ... >, tuple < BackStaticParamTypes ... > > res;
   
return res; return res;
} }
   
public: public:
template < class RealReturnType, class RealFirstParameterTypeBase > template < class RealReturnType, class ... RealParameterTypeBases >
class RegistratorWrapper : public RegistratorWrapperBase { class RegistratorWrapper : public RegistratorWrapperBase {
typedef typename match_cv_ref < FirstParameterType, RealFirstParameterTypeBase >::type RealFirstParameterType; function < RealReturnType ( FrontStaticParamTypes ..., typename match_cv_ref < DispatchedParameterTypes, RealParameterTypeBases >::type && ..., BackStaticParamTypes ... ) > callback;
std::function < RealReturnType ( RealFirstParameterType &&, StaticParamTypes ... ) > callback;
   
public: public:
ReturnType eval ( FirstParameterType && first, StaticParamTypes ... res ) { ReturnType eval ( FrontStaticParamTypes ... front, DispatchedParameterTypes && ... dispatched, BackStaticParamTypes ... back ) {
return ReturnType ( callback ( forward < RealFirstParameterType > ( static_cast < RealFirstParameterType && > ( first ) ), res ... ) ); 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 ) { RegistratorWrapper ( RealReturnType ( * callback ) ( FrontStaticParamTypes ..., typename match_cv_ref < DispatchedParameterTypes, RealParameterTypeBases >::type && ..., BackStaticParamTypes ... ) ) : callback ( callback ) {
if ( !getInstance ( ).registeredFunctions.insert ( std::make_pair ( std::type_index ( typeid ( RealFirstParameterType ) ), this ) ).second ) { if ( !getInstance ( ).registeredFunctions.insert ( make_pair ( make_tuple ( type_index ( typeid ( typename match_cv_ref < DispatchedParameterTypes, RealParameterTypeBases >::type ) ) ... ), this ) ).second ) {
std::string firstType = std::cstringToString ( std::type_name < RealFirstParameterType > ( ) ); 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 ) { static ReturnType dispatch ( FrontStaticParamTypes ... front, DispatchedParameterTypes && ... dispatched, BackStaticParamTypes ... back ) {
typename std::map < std::type_index, RegistratorWrapperBase * >::iterator callback = getInstance ( ).registeredFunctions.find ( std::type_index ( typeid ( first ) ) ); 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 ( ) ) { 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: ...@@ -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 */ } /* namespace std */
   
#endif /* MULTIPLE_DISPATCH_H_ */ #endif /* MULTIPLE_DISPATCH_H_ */
...@@ -178,7 +178,7 @@ public: ...@@ -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: public:
static int eval ( const Tmp2 & first ) { static int eval ( const Tmp2 & first ) {
std::cout << first << std::endl; std::cout << first << std::endl;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment