← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-pkg/yade/git-trunk] Rev 3855: Use variadic arguments in DynLibDispatcher.

 

------------------------------------------------------------
revno: 3855
committer: Anton Gladky <gladky.anton@xxxxxxxxx>
timestamp: Wed 2016-04-27 20:40:37 +0200
message:
  Use variadic arguments in DynLibDispatcher.
  
  Start to clean/update DynLibDispatcher. Reduce code duplocation.
  Code refactoring, preparatioin for Loki-removal.
modified:
  lib/multimethods/DynLibDispatcher.hpp
  lib/multimethods/Indexable.hpp
  pkg/common/Dispatching.cpp


--
lp:yade
https://code.launchpad.net/~yade-pkg/yade/git-trunk

Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-pkg/yade/git-trunk/+edit-subscription
=== modified file 'lib/multimethods/DynLibDispatcher.hpp'
--- lib/multimethods/DynLibDispatcher.hpp	2015-11-09 20:26:06 +0000
+++ lib/multimethods/DynLibDispatcher.hpp	2016-04-27 18:40:37 +0000
@@ -8,16 +8,13 @@
 
 #pragma once
 
-
-#include "Indexable.hpp"
-
-
+#include <lib/multimethods/Indexable.hpp>
 #include <lib/factory/ClassFactory.hpp>
 #include <lib/serialization/Serializable.hpp>
 
-#include<loki/Functor.h>
-#include<loki/Typelist.h>
-#include<loki/NullType.h>
+#include <loki/Functor.h>
+#include <loki/Typelist.h>
+#include <loki/NullType.h>
 // compat with former yade's local Loki
 #define TYPELIST_1 LOKI_TYPELIST_1
 #define TYPELIST_2 LOKI_TYPELIST_2
@@ -31,8 +28,16 @@
 #include <string>
 #include <ostream>
 
-struct DynLibDispatcher_Item2D{ int ix1, ix2; std::string functorName; DynLibDispatcher_Item2D(int a, int b, std::string c):ix1(a),ix2(b),functorName(c){}; };
-struct DynLibDispatcher_Item1D{ int ix1     ; std::string functorName; DynLibDispatcher_Item1D(int a,        std::string c):ix1(a),       functorName(c){}; };
+struct DynLibDispatcher_Item2D {
+	int ix1, ix2;
+	std::string functorName;
+	DynLibDispatcher_Item2D(int a, int b, std::string c):ix1(a),ix2(b),functorName(c){};
+};
+struct DynLibDispatcher_Item1D {
+	int ix1;
+	std::string functorName;
+	DynLibDispatcher_Item1D(int a, std::string c):ix1(a), functorName(c){};
+};
 ///
 /// base classes involved in multiple dispatch must be derived from Indexable
 ///
@@ -45,114 +50,62 @@
 				// 		FIXME: should use shared_ptr references, like this: DynLibDispatcher< TYPELIST_2( shared_ptr<PhysicalAction>& , shared_ptr<Body>& ) , ....
 	class Executor,		//	class which gives multivirtual function
 	class ResultType,	//	type returned by multivirtual function
-	class TList,		//	typelist of arguments passed to multivirtual function
+	class TList,
+				//	typelist of arguments passed to multivirtual function
 				//	WARNING: first arguments must be shared_ptr<BaseClass>, for details see FunctorWrapper
 				
-	bool autoSymmetry=true	//	true -	the function called is always the same,
-				//		only order of arguments is rearranged
-				//		to make correct function call, 
-				//		only go() is called
-				//		
-				//	false -	the function called is always different.
-				//		arguments order is not rearranged
-				//		go(), and goReverse() are called, respectively
-				//
+	bool autoSymmetry=true
+				/*true - the function called is always the same,
+						only order of arguments is rearranged
+						to make correct function call, 
+						only go() is called
+				
+					false - the function called is always different.
+						arguments order is not rearranged
+						go(), and goReverse() are called, respectively*/
 >
 class DynLibDispatcher
 {
-		// this template recursively defines a type for callBacks matrix, with required number of dimensions
+	// this template recursively defines a type for callBacks matrix, with required number of dimensions
 	private:
-		template<class T > struct Matrix
-		  {
-			typedef Loki::NullType ResultIterator;
-			typedef Loki::NullType ResultIteratorInt;
-		  };
+		template<class T > struct Matrix {
+				using ResultIterator = Loki::NullType;
+				using ResultIteratorInt = Loki::NullType;
+			};
 
-	template<class Head > struct Matrix< Loki::Typelist< Head, Loki::NullType > >
-		  {
-			typedef vector< shared_ptr< Executor > > 			Result;
-			typedef vector< int > 						ResultInt;
-			typedef typename vector< shared_ptr< Executor > >::iterator 	ResultIterator;
-			typedef vector< int >::iterator 				ResultIteratorInt;
+	template<class Head > struct Matrix< Loki::Typelist< Head, Loki::NullType > > {
+				using Result = vector< shared_ptr< Executor > >;
+				using ResultInt = vector< int >;
+				using ResultIterator = typename vector< shared_ptr< Executor > >::iterator;
+				using ResultIteratorInt = vector< int >::iterator;
 		  };
 
 	template<class Head, class Tail >
-		  struct Matrix< Loki::Typelist< Head, Tail > >
-		  {
-			// recursive typedef to get matrix of required dimensions
-			typedef typename Matrix< Tail >::Result 		InsideType;
-			typedef typename Matrix< Tail >::ResultInt 		InsideTypeInt;
-			typedef vector< InsideType > 				Result;
-			typedef vector< InsideTypeInt > 			ResultInt;
-			typedef typename vector< InsideType >::iterator 	ResultIterator;
-			typedef typename vector< InsideTypeInt >::iterator 	ResultIteratorInt;
-		  };
-		
-		// this template helps declaring iterators for each dimension of callBacks matrix
-	template<class T > struct GetTail
-		  {
-			typedef Loki::NullType Result;
-		  };
-
-	template<class Head, class Tail>
-		  struct GetTail< Loki::Typelist< Head , Tail > >
-		  {
-			typedef Tail Result;
-		  };
-
-	template<class Head >
-		  struct GetTail< Loki::Typelist< Head , Loki::NullType > >
-		  {
-			typedef Loki::NullType Result;
-		  };
-
-	template <typename G, typename T, typename U>
-		  struct Select
-		  {
-			typedef T Result;
-		  };
-	
-	template <typename T, typename U>
-		  struct Select<Loki::NullType, T, U>
-		  {
-			typedef U Result;
+		  struct Matrix< Loki::Typelist< Head, Tail > > {
+				// recursive typedef to get matrix of required dimensions
+				using InsideType = typename Matrix< Tail >::Result;
+				using InsideTypeInt = typename Matrix< Tail >::ResultInt;
+				using Result = vector< InsideType >;
+				using ResultInt = vector< InsideTypeInt >;
+				using ResultIterator = typename vector< InsideType >::iterator;
+				using ResultIteratorInt = typename vector< InsideTypeInt >::iterator;
 		  };
 
 	typedef typename Loki::TL::Append<  Loki::NullType , BaseClass >::Result BaseClassList;
-	typedef typename Loki::TL::TypeAtNonStrict<BaseClassList , 0>::Result	BaseClass1;  // 1D
-	typedef typename Loki::TL::TypeAtNonStrict<BaseClassList , 1>::Result	BaseClass2;  // 2D
-		
-	typedef typename GetTail< BaseClassList >::Result			Tail2; // 2D
-	typedef typename GetTail< Tail2 >::Result				Tail3; // 3D
-	typedef typename GetTail< Tail3 >::Result				Tail4; // 4D ...
-		
-	typedef typename Matrix< BaseClassList >::ResultIterator 		Iterator2; // outer iterator 2D
-		
-	typedef typename Matrix< BaseClassList >::ResultIteratorInt		IteratorInfo2;
-		
+	typedef typename Loki::TL::TypeAtNonStrict<BaseClassList , 0>::Result    BaseClass1;  // 1D
+	typedef typename Loki::TL::TypeAtNonStrict<BaseClassList , 1>::Result    BaseClass2;  // 2D
+	
+	
+	typedef typename Matrix< BaseClassList >::ResultIterator     Iterator2; // outer iterator 2D
+	typedef typename Matrix< BaseClassList >::ResultIteratorInt  IteratorInfo2;
+	
 	typedef typename Matrix< BaseClassList >::Result MatrixType;
 	typedef typename Matrix< BaseClassList >::ResultInt MatrixIntType;
-	MatrixType callBacks;		// multidimensional matrix that stores functors ( 1D, 2D, 3D, 4D, ....)
-	MatrixIntType callBacksInfo;	// multidimensional matrix for extra information about functors in the matrix
-						// currently used to remember if it is reversed functor
-						
-	// ParmNReal is defined to avoid ambigious function call for different dimensions of multimethod
-	typedef Loki::FunctorImpl<ResultType, TList > Impl;
-	typedef TList ParmList;
-	typedef Loki::NullType Parm1; 						// it's always at least 1D
-	typedef typename Impl::Parm2 Parm2Real;
-	typedef typename Select< Tail2 , Loki::NullType , Parm2Real >::Result Parm2; 	// 2D
-	typedef typename Impl::Parm3 Parm3Real;
-	typedef typename Select< Tail3 , Loki::NullType , Parm3Real >::Result Parm3; 	// 3D - to have 3D just working, without symmetry handling - change this line to be: typedef typename Impl::Parm3 Parm3;
-	typedef typename Impl::Parm4 Parm4Real;
-	typedef typename Select< Tail4 , Loki::NullType , Parm4Real >::Result Parm4;	// 4D - same as above
-	typedef typename Impl::Parm5 Parm5;
-	typedef typename Impl::Parm6 Parm6;
-	typedef typename Impl::Parm7 Parm7;
-	typedef typename Impl::Parm8 Parm8;
-	typedef typename Impl::Parm9 Parm9;
-	
- 	public:
+	MatrixType callBacks;        // multidimensional matrix that stores functors ( 1D, 2D, 3D, 4D, ....)
+	MatrixIntType callBacksInfo; // multidimensional matrix for extra information about functors in the matrix
+	                             // currently used to remember if it is reversed functor
+
+	public:
 		DynLibDispatcher()
 		  {
 			// FIXME - static_assert( typeid(BaseClass1) == typeid(Parm1) ); // 1D
@@ -160,10 +113,13 @@
 			clearMatrix();
 		};
 		  
-		void clearMatrix(){ callBacks.clear(); callBacksInfo.clear(); }
+		void clearMatrix() {
+			callBacks.clear();
+			callBacksInfo.clear();
+		}
 
 		shared_ptr<Executor> getExecutor(shared_ptr<BaseClass1>& arg1){
-		  	int ix1;
+			int ix1;
 			if(arg1->getClassIndex()<0) throw runtime_error("No functor for type "+arg1->getClassName()+" (index "+boost::lexical_cast<string>(arg1->getClassIndex())+"), since the index is invalid (negative).");
 			if(locateMultivirtualFunctor1D(ix1,arg1)) return callBacks[ix1];
 			return shared_ptr<Executor>();
@@ -187,12 +143,22 @@
 
 		/*! Return representation of the dispatch matrix as vector of int,string (i.e. index,functor name) */
 		vector<DynLibDispatcher_Item1D> dataDispatchMatrix1D(){
-			vector<DynLibDispatcher_Item1D> ret; for(size_t i=0; i<callBacks.size(); i++){ if(callBacks[i]) ret.push_back(DynLibDispatcher_Item1D(i,callBacks[i]->getClassName())); }
+			vector<DynLibDispatcher_Item1D> ret;
+			for(size_t i=0; i<callBacks.size(); i++) {
+				if(callBacks[i]) ret.push_back(DynLibDispatcher_Item1D(i,callBacks[i]->getClassName()));
+			}
 			return ret;
 		}
 		/*! Return representation of the dispatch matrix as vector of int,int,string (i.e. index1,index2,functor name) */
 		vector<DynLibDispatcher_Item2D> dataDispatchMatrix2D(){
-			vector<DynLibDispatcher_Item2D> ret; for(size_t i=0; i<callBacks.size(); i++){ for(size_t j=0; j<callBacks[i].size(); j++){ /*cerr<<"["<<i<<","<<j<<"]";*/ if(callBacks[i][j]) { /* cerr<<"()"; */ ret.push_back(DynLibDispatcher_Item2D(i,j,callBacks[i][j]->getClassName())); } } }
+			vector<DynLibDispatcher_Item2D> ret;
+			for(size_t i=0; i<callBacks.size(); i++) {
+				for(size_t j=0; j<callBacks[i].size(); j++) {
+					if(callBacks[i][j]) {
+						ret.push_back(DynLibDispatcher_Item2D(i,j,callBacks[i][j]->getClassName()));
+					}
+				}
+			}
 			return ret;
 		}
 
@@ -205,9 +171,11 @@
 		}
 		/*! Dump 2d dispatch matrix to given stream. */
 		std::ostream& dumpDispatchMatrix2D(std::ostream& out, const string& prefix=""){
-			for(size_t i=0; i<callBacks.size(); i++){	for(size_t j=0; j<callBacks.size(); j++){
-				if(callBacks[i][j]) out<<prefix<<i<<"+"<<j<<" -> "<<callBacks[i][j]->getClassName()<<std::endl;
-			}}
+			for(size_t i=0; i<callBacks.size(); i++) {
+				for(size_t j=0; j<callBacks.size(); j++) {
+					if(callBacks[i][j]) out<<prefix<<i<<"+"<<j<<" -> "<<callBacks[i][j]->getClassName()<<std::endl;
+				}
+			}
 			return out;
 		}
 
@@ -328,7 +296,7 @@
 			return false; // FIXME - this line should be not needed
 		}
 
-		bool locateMultivirtualFunctor2D(int& index1, int& index2, shared_ptr<BaseClass1>& base1,shared_ptr<BaseClass2>& base2) {
+		bool locateMultivirtualFunctor2D(int& index1, int& index2, shared_ptr<BaseClass1>& base1, shared_ptr<BaseClass2>& base2) {
 			//#define _DISP_TRACE(msg) cerr<<"@DT@"<<__LINE__<<" "<<msg<<endl;
 			#define _DISP_TRACE(msg)
 			if(callBacks.empty()) return false;
@@ -353,9 +321,12 @@
 				e.g. if MetaInteractingGeometry2AABB is not in BoundingVoumeMetaEngine, it is looked up at every step.
 
 			*/
-			if(callBacks[index1][index2]){ _DISP_TRACE("Direct hit at ["<<index1<<"]["<<index2<<"] → "<<callBacks[index1][index2]->getClassName()); return true; }
+			if(callBacks[index1][index2]) {
+				_DISP_TRACE("Direct hit at ["<<index1<<"]["<<index2<<"] → "<<callBacks[index1][index2]->getClassName());
+				return true;
+			}
 			int foundIx1,foundIx2; int maxDp1=-1, maxDp2=-1;
-			// if(base1->getBaseClassIndex(0)<0) maxDp1=0; if(base2->getBaseClassIndex(0)<0) maxDp2=0;
+			
 			for(int dist=1; ; dist++){
 				bool distTooBig=true;
 				foundIx1=foundIx2=-1; // found no dispatch at this depth yet
@@ -364,7 +335,8 @@
 					if((maxDp1>=0 && dp1>maxDp1) || (maxDp2>=0 && dp2>maxDp2)) continue;
 					_DISP_TRACE(" Trying indices with depths "<<dp1<<" and "<<dp2<<", dist="<<dist);
 					int ix1=dp1>0?base1->getBaseClassIndex(dp1):index1, ix2=dp2>0?base2->getBaseClassIndex(dp2):index2;
-					if(ix1<0) maxDp1=dp1; if(ix2<0) maxDp2=dp2;
+					if(ix1<0) maxDp1=dp1;
+					if(ix2<0) maxDp2=dp2;
 					if(ix1<0 || ix2<0) continue; // hierarchy height exceeded in either dimension
 					distTooBig=false;
 					if(callBacks[ix1][ix2]){
@@ -373,324 +345,66 @@
 							dumpDispatchMatrix2D(cerr,"AMBIGUOUS: "); throw runtime_error("Ambiguous dispatch.");
 						}
 						foundIx1=ix1; foundIx2=ix2;
-						callBacks[index1][index2]=callBacks[ix1][ix2]; callBacksInfo[index1][index2]=callBacksInfo[ix1][ix2];
+						callBacks[index1][index2]=callBacks[ix1][ix2];
+						callBacksInfo[index1][index2]=callBacksInfo[ix1][ix2];
 						_DISP_TRACE("Found callback ["<<ix1<<"]["<<ix2<<"] → "<<callBacks[ix1][ix2]->getClassName());
 					}
 				}
 				if(foundIx1!=-1) return true;
-				if(distTooBig){ _DISP_TRACE("Undefined dispatch, dist="<<dist); return false; /* undefined dispatch */ }
+				if(distTooBig){
+					_DISP_TRACE("Undefined dispatch, dist="<<dist);
+					return false; /* undefined dispatch */
+				}
 			}
 		};
-
-		
 		
 // calling multivirtual function, 1D
+		template<typename... Args>
+		ResultType operator() (shared_ptr<BaseClass1>& base, Args... args)
+		{
+			int index;
+			if( locateMultivirtualFunctor1D(index,base) )
+				return (callBacks[index])->go(base, args...);
+			else	return ResultType();
+		}
+		
 
-		ResultType operator() (shared_ptr<BaseClass1>& base)
-		{
-			int index;
-			if( locateMultivirtualFunctor1D(index,base) )
-				return (callBacks[index])->go(base);
-			else	return ResultType();
-		}
-		
-		ResultType operator() (shared_ptr<BaseClass1>& base, Parm2 p2)
-		{
-			int index;
-			if( locateMultivirtualFunctor1D(index,base) )
-				return (callBacks[index])->go(base, p2);
-			else	return ResultType();
-		}
-		
-		ResultType operator() (shared_ptr<BaseClass1>& base, Parm2 p2, Parm3 p3)
-		{
-			int index;
-			if( locateMultivirtualFunctor1D(index,base) )
-				return (callBacks[index])->go(base, p2, p3);
-			else	return ResultType();
-		}
-		
-		ResultType operator() (shared_ptr<BaseClass1>& base, Parm2 p2, Parm3 p3, Parm4 p4)
-		{
-			int index;
-			if( locateMultivirtualFunctor1D(index,base) )
-				return (callBacks[index])->go(base, p2, p3, p4);
-			else	return ResultType();
-		}
-		
-		ResultType operator() (shared_ptr<BaseClass1>& base, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5)
-		{
-			int index;
-			if( locateMultivirtualFunctor1D(index,base) )
-				return (callBacks[index])->go(base, p2, p3, p4, p5);
-			else	return ResultType();
-		}
-		
-		ResultType operator() (shared_ptr<BaseClass1>& base, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, Parm6 p6)
-		{
-			int index;
-			if( locateMultivirtualFunctor1D(index,base) )
-				return (callBacks[index])->go(base, p2, p3, p4, p5, p6);
-			else	return ResultType();
-		}
-		
-		ResultType operator() (shared_ptr<BaseClass1>& base, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, Parm6 p6, Parm7 p7)
-		{
-			int index;
-			if( locateMultivirtualFunctor1D(index,base) )
-				return (callBacks[index])->go(base, p2, p3, p4, p5, p6, p7);
-			else	return ResultType();
-		}
-		
-		ResultType operator() (shared_ptr<BaseClass1>& base, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, Parm6 p6, Parm7 p7, Parm8 p8)
-		{
-			int index;
-			if( locateMultivirtualFunctor1D(index,base) )
-				return (callBacks[index])->go(base, p2, p3, p4, p5, p6, p7, p8);
-			else	return ResultType();
-		}
-		
-		ResultType operator() (shared_ptr<BaseClass1>& base, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9)
-		{
-			int index;
-			if( locateMultivirtualFunctor1D(index,base) )
-				return (callBacks[index])->go(base, p2, p3, p4, p5, p6, p7, p8, p9);
-			else	return ResultType();
-		}
-	
 // calling multivirtual function, 2D, 
 // symmetry handling in private struct
-
-/// @cond 
 	private:
-		template< bool useSymmetry, class BaseClassTrait1, class BaseClassTrait2, class ParmTrait3, class ParmTrait4, class ParmTrait5, class ParmTrait6,
-				class ParmTrait7, class ParmTrait8, class ParmTrait9 >
+		template< bool useSymmetry, class BaseClassTrait1, class BaseClassTrait2, typename... Args>
 		struct InvocationTraits
 		{
-			static ResultType doDispatch( shared_ptr<Executor>& ex, shared_ptr<BaseClassTrait1> base1, shared_ptr<BaseClassTrait2> base2 )
-			{	
-				return ex->goReverse	(base1, base2);	
-			}	
-			static ResultType doDispatch( shared_ptr<Executor>& ex, shared_ptr<BaseClassTrait1> base1, shared_ptr<BaseClassTrait2> base2, ParmTrait3 p3)
-			{
-				return ex->goReverse	(base1, base2, p3);
-			}
-			static ResultType doDispatch( shared_ptr<Executor>& ex, shared_ptr<BaseClassTrait1> base1, shared_ptr<BaseClassTrait2> base2, ParmTrait3 p3,
-						ParmTrait4 p4)
-			{
-				return ex->goReverse	(base1, base2, p3, p4);
-			}
-			static ResultType doDispatch( shared_ptr<Executor>& ex, shared_ptr<BaseClassTrait1> base1, shared_ptr<BaseClassTrait2> base2, ParmTrait3 p3,
-						ParmTrait4 p4, ParmTrait5 p5)
-			{
-				return ex->goReverse	(base1, base2, p3, p4, p5);
-			}
-			static ResultType doDispatch( shared_ptr<Executor>& ex, shared_ptr<BaseClassTrait1> base1, shared_ptr<BaseClassTrait2> base2, ParmTrait3 p3,
-						ParmTrait4 p4, ParmTrait5 p5, ParmTrait6 p6)
-			{	
-				return ex->goReverse	(base1, base2, p3, p4, p5, p6);
-			}
-			static ResultType doDispatch( shared_ptr<Executor>& ex, shared_ptr<BaseClassTrait1> base1, shared_ptr<BaseClassTrait2> base2, ParmTrait3 p3,
-						ParmTrait4 p4, ParmTrait5 p5, ParmTrait6 p6, ParmTrait7 p7)
-			{	
-				return ex->goReverse	(base1, base2, p3, p4, p5, p6, p7);
-			}
-			static ResultType doDispatch( shared_ptr<Executor>& ex, shared_ptr<BaseClassTrait1> base1, shared_ptr<BaseClassTrait2> base2, ParmTrait3 p3,
-						ParmTrait4 p4, ParmTrait5 p5, ParmTrait6 p6, ParmTrait7 p7, ParmTrait8 p8)
-			{	
-				return ex->goReverse	(base1, base2, p3, p4, p5, p6, p7, p8);
-			}
-			static ResultType doDispatch( shared_ptr<Executor>& ex, shared_ptr<BaseClassTrait1> base1, shared_ptr<BaseClassTrait2> base2, ParmTrait3 p3,
-						ParmTrait4 p4, ParmTrait5 p5, ParmTrait6 p6, ParmTrait7 p7, ParmTrait8 p8, ParmTrait9 p9)
-			{	
-				return ex->goReverse	(base1, base2, p3, p4, p5, p6, p7, p8, p9);
+			static ResultType doDispatch(shared_ptr<Executor>& ex, shared_ptr<BaseClassTrait1> base1, shared_ptr<BaseClassTrait2> base2, Args... args)
+			{
+				return ex->goReverse (base1, base2, args...);
 			}
 		};
-		template< class BaseClassTrait, class ParmTrait3, class ParmTrait4, class ParmTrait5, class ParmTrait6
-					, class ParmTrait7, class ParmTrait8, class ParmTrait9>
-		struct InvocationTraits< true , BaseClassTrait, BaseClassTrait, ParmTrait3, ParmTrait4, ParmTrait5, ParmTrait6
-					, ParmTrait7, ParmTrait8, ParmTrait9 >
+		template< class BaseClassTrait, typename... Args>
+		struct InvocationTraits< true , BaseClassTrait, BaseClassTrait, Args... >
 		{
-			static ResultType doDispatch( shared_ptr<Executor>& ex , shared_ptr<BaseClassTrait> base1, shared_ptr<BaseClassTrait> base2 )
-			{
-				return ex->go		(base2, base1 );
-			}
-			static ResultType doDispatch( shared_ptr<Executor>& ex , shared_ptr<BaseClassTrait> base1, shared_ptr<BaseClassTrait> base2, ParmTrait3 p3)
-			{
-				return ex->go		(base2, base1, p3);
-			}
-			static ResultType doDispatch( shared_ptr<Executor>& ex , shared_ptr<BaseClassTrait> base1, shared_ptr<BaseClassTrait> base2, ParmTrait3 p3,
-						ParmTrait4 p4)
-			{
-				return ex->go		(base2, base1, p3, p4);
-			}
-			static ResultType doDispatch( shared_ptr<Executor>& ex , shared_ptr<BaseClassTrait> base1, shared_ptr<BaseClassTrait> base2, ParmTrait3 p3,
-						ParmTrait4 p4, ParmTrait5 p5)
-			{	
-				return ex->go		(base2, base1, p3, p4, p5);
-			}
-			static ResultType doDispatch( shared_ptr<Executor>& ex , shared_ptr<BaseClassTrait> base1, shared_ptr<BaseClassTrait> base2, ParmTrait3 p3,
-						ParmTrait4 p4, ParmTrait5 p5, ParmTrait6 p6)
-			{	
-				return ex->go		(base2, base1, p3, p4, p5, p6);
-			}
-			static ResultType doDispatch( shared_ptr<Executor>& ex , shared_ptr<BaseClassTrait> base1, shared_ptr<BaseClassTrait> base2, ParmTrait3 p3,
-						ParmTrait4 p4, ParmTrait5 p5, ParmTrait6 p6, ParmTrait7 p7)
-			{	
-				return ex->go		(base2, base1, p3, p4, p5, p6, p7);
-			}
-			static ResultType doDispatch( shared_ptr<Executor>& ex , shared_ptr<BaseClassTrait> base1, shared_ptr<BaseClassTrait> base2, ParmTrait3 p3,
-						ParmTrait4 p4, ParmTrait5 p5, ParmTrait6 p6, ParmTrait7 p7, ParmTrait8 p8)
-			{	
-				return ex->go		(base2, base1, p3, p4, p5, p6, p7, p8);
-			}
-			static ResultType doDispatch( shared_ptr<Executor>& ex , shared_ptr<BaseClassTrait> base1, shared_ptr<BaseClassTrait> base2, ParmTrait3 p3,
-						ParmTrait4 p4, ParmTrait5 p5, ParmTrait6 p6, ParmTrait7 p7, ParmTrait8 p8, ParmTrait9 p9)
-			{	
-				return ex->go		(base2, base1, p3, p4, p5, p6, p7, p8, p9);
+			static ResultType doDispatch( shared_ptr<Executor>& ex , shared_ptr<BaseClassTrait> base1, shared_ptr<BaseClassTrait> base2, Args... args)
+			{
+				return ex->go (base2, base1, args...);
 			}
 		};
 
 // calling multivirtual function, 2D, public interface
 	public:
-		ResultType operator() (shared_ptr<BaseClass1>& base1,shared_ptr<BaseClass2>& base2)
-		{
-			int index1, index2;
-			if( locateMultivirtualFunctor2D(index1,index2,base1,base2) )
-			{
-				if(callBacksInfo[index1][index2])	// reversed
-				{
-					typedef InvocationTraits<autoSymmetry, BaseClass1, BaseClass2, Parm3, Parm4, Parm5, Parm6,
-						Parm7, Parm8, Parm9 > CallTraits;
-					return CallTraits::doDispatch( callBacks[index1][index2] , base1, base2 );
-				}
-				else
-					return (callBacks[index1][index2] )->go			(base1, base2 );
-			}
-			else	return ResultType();
-		}
-		
-		ResultType operator() (shared_ptr<BaseClass1>& base1,shared_ptr<BaseClass2>& base2, Parm3 p3)
-		{
-			int index1, index2;
-			if( locateMultivirtualFunctor2D(index1,index2,base1,base2) )
-			{
-				if(callBacksInfo[index1][index2])	// reversed
-				{
-					typedef InvocationTraits<autoSymmetry, BaseClass1, BaseClass2, Parm3, Parm4, Parm5, Parm6,
-						Parm7, Parm8, Parm9> CallTraits;
-					return CallTraits::doDispatch( callBacks[index1][index2] , base1, base2, p3);
-				}
-				else
-					return (callBacks[index1][index2] )->go			(base1, base2, p3 );
-			}
-			else	return ResultType();
-		}
-		
-		ResultType operator() (shared_ptr<BaseClass1>& base1,shared_ptr<BaseClass2>& base2, Parm3 p3, Parm4 p4)
-		{
-			int index1, index2;
-			if( locateMultivirtualFunctor2D(index1,index2,base1,base2) )
-			{
-				if(callBacksInfo[index1][index2])	// reversed
-				{
-					typedef InvocationTraits<autoSymmetry, BaseClass1, BaseClass2, Parm3, Parm4, Parm5, Parm6,
-						Parm7, Parm8, Parm9> CallTraits;
-					return CallTraits::doDispatch( callBacks[index1][index2] , base1, base2, p3, p4 );
-				}
-				else
-					return (callBacks[index1][index2] )->go			(base1, base2, p3, p4 );
-			}
-			else	return ResultType();
-		}
-		
-		ResultType operator() (shared_ptr<BaseClass1>& base1,shared_ptr<BaseClass2>& base2, Parm3 p3, Parm4 p4, Parm5 p5)
-		{
-			int index1, index2;
-			if( locateMultivirtualFunctor2D(index1,index2,base1,base2) )
-			{
-				if(callBacksInfo[index1][index2])	// reversed
-				{
-					typedef InvocationTraits<autoSymmetry, BaseClass1, BaseClass2, Parm3, Parm4, Parm5, Parm6,
-						Parm7, Parm8, Parm9> CallTraits;
-					return CallTraits::doDispatch( callBacks[index1][index2] , base1, base2, p3, p4, p5 );
-				}
-				else
-					return (callBacks[index1][index2] )->go			(base1, base2, p3, p4, p5 );
-			}
-			else	return ResultType();
-		}
-		
-		ResultType operator() (shared_ptr<BaseClass1>& base1,shared_ptr<BaseClass2>& base2, Parm3 p3, Parm4 p4, Parm5 p5, Parm6 p6)
-		{
-			int index1, index2;
-			if( locateMultivirtualFunctor2D(index1,index2,base1,base2) )
-			{
-				if(callBacksInfo[index1][index2])	// reversed
-				{
-					typedef InvocationTraits<autoSymmetry, BaseClass1, BaseClass2, Parm3, Parm4, Parm5, Parm6,
-						Parm7, Parm8, Parm9> CallTraits;
-					return CallTraits::doDispatch( callBacks[index1][index2] , base1, base2, p3, p4, p5, p6 );
-				}
-				else
-					return (callBacks[index1][index2] )->go			(base1, base2, p3, p4, p5, p6 );
-			}
-			else	return ResultType();
-		}
-		
-		ResultType operator() (shared_ptr<BaseClass1>& base1,shared_ptr<BaseClass2>& base2, Parm3 p3, Parm4 p4, Parm5 p5, Parm6 p6,
-						Parm7 p7)
-		{
-			int index1, index2;
-			if( locateMultivirtualFunctor2D(index1,index2,base1,base2) )
-			{
-				if(callBacksInfo[index1][index2])	// reversed
-				{
-					typedef InvocationTraits<autoSymmetry, BaseClass1, BaseClass2, Parm3, Parm4, Parm5, Parm6,
-						Parm7, Parm8, Parm9> CallTraits;
-					return CallTraits::doDispatch( callBacks[index1][index2] , base1, base2, p3, p4, p5, p6, p7 );
-				}
-				else
-					return (callBacks[index1][index2] )->go			(base1, base2, p3, p4, p5, p6, p7 );
-			}
-			else	return ResultType();
-		}
-		
-		ResultType operator() (shared_ptr<BaseClass1>& base1,shared_ptr<BaseClass2>& base2, Parm3 p3, Parm4 p4, Parm5 p5, Parm6 p6,
-						Parm7 p7, Parm8 p8)
-		{
-			int index1, index2;
-			if( locateMultivirtualFunctor2D(index1,index2,base1,base2) )
-			{
-				if(callBacksInfo[index1][index2])	// reversed
-				{
-					typedef InvocationTraits<autoSymmetry, BaseClass1, BaseClass2, Parm3, Parm4, Parm5, Parm6,
-						Parm7, Parm8, Parm9> CallTraits;
-					return CallTraits::doDispatch( callBacks[index1][index2] , base1, base2, p3, p4, p5, p6, p7, p8);
-				}
-				else
-					return (callBacks[index1][index2] )->go			(base1, base2, p3, p4, p5, p6, p7, p8 );
-			}
-			else	return ResultType();
-		}
-		
-		ResultType operator() (shared_ptr<BaseClass1>& base1,shared_ptr<BaseClass2>& base2, Parm3 p3, Parm4 p4, Parm5 p5, Parm6 p6,
-						Parm7 p7, Parm8 p8, Parm9 p9)
-		{
-			int index1, index2;
-			if( locateMultivirtualFunctor2D(index1,index2,base1,base2) )
-			{
-				if(callBacksInfo[index1][index2])	// reversed
-				{
-					typedef InvocationTraits<autoSymmetry, BaseClass1, BaseClass2, Parm3, Parm4, Parm5, Parm6,
-						Parm7, Parm8, Parm9> CallTraits;
-					return CallTraits::doDispatch( callBacks[index1][index2] , base1, base2, p3, p4, p5, p6, p7, p8, p9 );
-				}
-				else
-					return (callBacks[index1][index2] )->go			(base1, base2, p3, p4, p5, p6, p7, p8, p9 );
+		template<typename... Args>
+		ResultType operator() (shared_ptr<BaseClass1>& base1, shared_ptr<BaseClass2>& base2, Args... args)
+		{
+			int index1, index2;
+			if( locateMultivirtualFunctor2D(index1,index2,base1,base2) )
+			{
+				if(callBacksInfo[index1][index2])// reversed
+				{
+					using CallTraits=InvocationTraits<autoSymmetry, BaseClass1, BaseClass2, Args...> ;
+					return CallTraits::doDispatch( callBacks[index1][index2] , base1, base2, args...);
+				}
+				else
+					return (callBacks[index1][index2] )->go(base1, base2, args...);
 			}
 			else	return ResultType();
 		}
 };
-
-

=== modified file 'lib/multimethods/Indexable.hpp'
--- lib/multimethods/Indexable.hpp	2014-07-21 18:17:38 +0000
+++ lib/multimethods/Indexable.hpp	2016-04-27 18:40:37 +0000
@@ -11,8 +11,8 @@
 #pragma once
 
 #include <boost/scoped_ptr.hpp>
-#include<stdexcept>
-#include<string>
+#include <stdexcept>
+#include <string>
 
 /*! \brief Abstract interface for all Indexable class.
 	An indexable class is a class that will be managed by a MultiMethodManager.

=== modified file 'pkg/common/Dispatching.cpp'
--- pkg/common/Dispatching.cpp	2015-11-06 20:00:30 +0000
+++ pkg/common/Dispatching.cpp	2016-04-27 18:40:37 +0000
@@ -92,7 +92,7 @@
 	} else {
 		shared_ptr<Interaction> I(new Interaction(b1->getId(),b2->getId()));
 		I->cellDist=cellDist;
-		b1->shape && b2->shape && operator()(b1->shape,b2->shape,*b1->state,*b2->state,shift2,/*force*/ false,I);
+		b1->shape && b2->shape && I->functorCache.geom->go(b1->shape,b2->shape,*b1->state,*b2->state,shift2,/*force*/true,I);
 		return I;
 	}
 }
@@ -124,11 +124,12 @@
 			bool wasReal=I->isReal();
 			if (!b1->shape || !b2->shape) { assert(!wasReal); continue; } // some bodies do not have shape
 			bool geomCreated;
+			//const bool forceFalse=false;
 			if(!isPeriodic){
-				geomCreated=operator()(b1->shape, b2->shape, *b1->state, *b2->state, Vector3r::Zero(), /*force*/ false, I);
+				geomCreated=I->functorCache.geom->go(b1->shape,b2->shape, *b1->state, *b2->state, Vector3r::Zero(), /*force*/false, I);
 			} else{
 				Vector3r shift2=cellHsize*I->cellDist.cast<Real>();
-				geomCreated=operator()(b1->shape, b2->shape, *b1->state, *b2->state, shift2, /*force*/ false, I);
+				geomCreated=I->functorCache.geom->go(b1->shape,b2->shape,*b1->state,*b2->state,shift2,/*force*/false,I);
 			}
 			// reset && erase interaction that existed but now has no geometry anymore
 			if(wasReal && !geomCreated){ scene->interactions->requestErase(I); }