diff --git a/alib2algo/src/arbology/exact/ExactSubtreeMatch.cpp b/alib2algo/src/arbology/exact/ExactSubtreeMatch.cpp
index 08b61e361df55bd10bf0ee4a2efd5fa1e79a56b2..f711c038fe95fa222086a4c9e13e36fd76a93d88 100644
--- a/alib2algo/src/arbology/exact/ExactSubtreeMatch.cpp
+++ b/alib2algo/src/arbology/exact/ExactSubtreeMatch.cpp
@@ -64,7 +64,7 @@ std::set<unsigned> ExactSubtreeMatch::match(const tree::UnrankedTree& subject, c
 	return occ;
 }
 
-auto ExactSubtreeMatchUnrankedTreeUnrankedTree = ExactSubtreeMatch::RegistratorWrapper<std::set<unsigned>, tree::UnrankedTree, tree::UnrankedTree>(ExactSubtreeMatch::getInstance(), ExactSubtreeMatch::match);
+auto ExactSubtreeMatchUnrankedTree = ExactSubtreeMatch::RegistratorWrapper<std::set<unsigned>, tree::UnrankedTree>(ExactSubtreeMatch::getInstance(), ExactSubtreeMatch::match);
 
 std::set<unsigned> ExactSubtreeMatch::match(const tree::RankedTree& subject, const tree::RankedTree& pattern) {
 	unsigned i = 0;
@@ -73,7 +73,7 @@ std::set<unsigned> ExactSubtreeMatch::match(const tree::RankedTree& subject, con
 	return occ;
 }
 
-auto ExactSubtreeMatchRankedTreeRankedTree = ExactSubtreeMatch::RegistratorWrapper<std::set<unsigned>, tree::RankedTree, tree::RankedTree>(ExactSubtreeMatch::getInstance(), ExactSubtreeMatch::match);
+auto ExactSubtreeMatchRankedTree = ExactSubtreeMatch::RegistratorWrapper<std::set<unsigned>, tree::RankedTree>(ExactSubtreeMatch::getInstance(), ExactSubtreeMatch::match);
 
 std::set<unsigned> ExactSubtreeMatch::match(const tree::PrefixRankedTree& subject, const tree::PrefixRankedTree& pattern) {
 	std::set<unsigned> occ;
@@ -89,7 +89,7 @@ std::set<unsigned> ExactSubtreeMatch::match(const tree::PrefixRankedTree& subjec
 	return occ;
 }
 
-auto ExactSubtreeMatchPrefixRankedTreePrefixRankedTree = ExactSubtreeMatch::RegistratorWrapper<std::set<unsigned>, tree::PrefixRankedTree, tree::PrefixRankedTree>(ExactSubtreeMatch::getInstance(), ExactSubtreeMatch::match);
+auto ExactSubtreeMatchPrefixRankedTree = ExactSubtreeMatch::RegistratorWrapper<std::set<unsigned>, tree::PrefixRankedTree>(ExactSubtreeMatch::getInstance(), ExactSubtreeMatch::match);
 
 std::set<unsigned> ExactSubtreeMatch::match(const tree::PrefixRankedBarTree& subject, const tree::PrefixRankedBarTree& pattern) {
 	std::set<unsigned> occ;
@@ -105,7 +105,7 @@ std::set<unsigned> ExactSubtreeMatch::match(const tree::PrefixRankedBarTree& sub
 	return occ;
 }
 
-auto ExactSubtreeMatchPrefixRankedBarTreePrefixRankedBarTree = ExactSubtreeMatch::RegistratorWrapper<std::set<unsigned>, tree::PrefixRankedBarTree, tree::PrefixRankedBarTree>(ExactSubtreeMatch::getInstance(), ExactSubtreeMatch::match);
+auto ExactSubtreeMatchPrefixRankedBarTree = ExactSubtreeMatch::RegistratorWrapper<std::set<unsigned>, tree::PrefixRankedBarTree>(ExactSubtreeMatch::getInstance(), ExactSubtreeMatch::match);
 
 } /* namespace exact */
 
diff --git a/alib2algo/src/arbology/exact/ExactSubtreeMatch.h b/alib2algo/src/arbology/exact/ExactSubtreeMatch.h
index ee63da87503ae4da7366cf09d65a0c08ba0976c8..c596fd04190fa0ecd0c1623ad056696b03ba917c 100644
--- a/alib2algo/src/arbology/exact/ExactSubtreeMatch.h
+++ b/alib2algo/src/arbology/exact/ExactSubtreeMatch.h
@@ -18,7 +18,7 @@ namespace arbology {
 
 namespace exact {
 
-class ExactSubtreeMatch : public std::DoubleDispatch<std::set<unsigned>, tree::TreeBase, tree::TreeBase> {
+class ExactSubtreeMatch : public std::PromotingDoubleDispatch<std::set<unsigned>, tree::TreeBase> {
 public:
 	/**
 	 * Performs conversion.
diff --git a/alib2algo/src/regexp/transform/RegExpAlternate.cpp b/alib2algo/src/regexp/transform/RegExpAlternate.cpp
index 75748fda8634b22874da85d7803820b3d6d80d30..5824eab64083953c150d1d47a27ba3b2d6db42f2 100644
--- a/alib2algo/src/regexp/transform/RegExpAlternate.cpp
+++ b/alib2algo/src/regexp/transform/RegExpAlternate.cpp
@@ -20,7 +20,7 @@ regexp::FormalRegExp RegExpAlternate::alternate(const regexp::FormalRegExp& firs
 	return regexp::FormalRegExp(regexp::FormalRegExpAlternation(first.getRegExp(), second.getRegExp()));
 }
 
-auto RegExpAlternateFormalRegExpFormalRegExp = RegExpAlternate::RegistratorWrapper<regexp::FormalRegExp, regexp::FormalRegExp, regexp::FormalRegExp>(RegExpAlternate::getInstance(), RegExpAlternate::alternate);
+auto RegExpAlternateFormalRegExp = RegExpAlternate::RegistratorWrapper<regexp::FormalRegExp, regexp::FormalRegExp>(RegExpAlternate::getInstance(), RegExpAlternate::alternate);
 
 regexp::UnboundedRegExp RegExpAlternate::alternate(const regexp::UnboundedRegExp& first, const regexp::UnboundedRegExp& second) {
 	regexp::UnboundedRegExpAlternation con;
@@ -29,6 +29,6 @@ regexp::UnboundedRegExp RegExpAlternate::alternate(const regexp::UnboundedRegExp
 	return regexp::UnboundedRegExp(con);
 }
 
-auto RegExpAlternateUnboundedRegExpUnboundedRegExp = RegExpAlternate::RegistratorWrapper<regexp::UnboundedRegExp, regexp::UnboundedRegExp, regexp::UnboundedRegExp>(RegExpAlternate::getInstance(), RegExpAlternate::alternate);
+auto RegExpAlternateUnboundedRegExp = RegExpAlternate::RegistratorWrapper<regexp::UnboundedRegExp, regexp::UnboundedRegExp>(RegExpAlternate::getInstance(), RegExpAlternate::alternate);
 
 } /* namespace regexp */
diff --git a/alib2algo/src/regexp/transform/RegExpAlternate.h b/alib2algo/src/regexp/transform/RegExpAlternate.h
index fda432cce98b794e6d5a5dd0a21dc94df017cff9..b915c1b9f887481ac72345b01cda5256a7c6d382 100644
--- a/alib2algo/src/regexp/transform/RegExpAlternate.h
+++ b/alib2algo/src/regexp/transform/RegExpAlternate.h
@@ -20,7 +20,7 @@ namespace regexp {
  * Alternates two regexpses
  *
  */
-class RegExpAlternate : public std::DoubleDispatch<regexp::RegExp, regexp::RegExpBase, regexp::RegExpBase> {
+class RegExpAlternate : public std::PromotingDoubleDispatch<regexp::RegExp, regexp::RegExpBase> {
 public:
 	static regexp::RegExp alternate(const regexp::RegExp& first, const regexp::RegExp& second);
 
diff --git a/alib2algo/src/regexp/transform/RegExpConcatenate.cpp b/alib2algo/src/regexp/transform/RegExpConcatenate.cpp
index 514baf7d1aff5f9b2c82c53b1c4497d1130683f4..ddb89264b2e7de363b7c1f9c2ed2b77d43288cf0 100644
--- a/alib2algo/src/regexp/transform/RegExpConcatenate.cpp
+++ b/alib2algo/src/regexp/transform/RegExpConcatenate.cpp
@@ -20,7 +20,7 @@ regexp::FormalRegExp RegExpConcatenate::concatenate(const regexp::FormalRegExp&
 	return regexp::FormalRegExp(regexp::FormalRegExpConcatenation(first.getRegExp(), second.getRegExp()));
 }
 
-auto RegExpConcatenateFormalRegExpFormalRegExp = RegExpConcatenate::RegistratorWrapper<regexp::FormalRegExp, regexp::FormalRegExp, regexp::FormalRegExp>(RegExpConcatenate::getInstance(), RegExpConcatenate::concatenate);
+auto RegExpConcatenateFormalRegExp = RegExpConcatenate::RegistratorWrapper<regexp::FormalRegExp, regexp::FormalRegExp>(RegExpConcatenate::getInstance(), RegExpConcatenate::concatenate);
 
 regexp::UnboundedRegExp RegExpConcatenate::concatenate(const regexp::UnboundedRegExp& first, const regexp::UnboundedRegExp& second) {
 	regexp::UnboundedRegExpConcatenation con;
@@ -29,6 +29,6 @@ regexp::UnboundedRegExp RegExpConcatenate::concatenate(const regexp::UnboundedRe
 	return regexp::UnboundedRegExp(con);
 }
 
-auto RegExpConcatenateUnboundedRegExpUnboundedRegExp = RegExpConcatenate::RegistratorWrapper<regexp::UnboundedRegExp, regexp::UnboundedRegExp, regexp::UnboundedRegExp>(RegExpConcatenate::getInstance(), RegExpConcatenate::concatenate);
+auto RegExpConcatenateUnboundedRegExp = RegExpConcatenate::RegistratorWrapper<regexp::UnboundedRegExp, regexp::UnboundedRegExp>(RegExpConcatenate::getInstance(), RegExpConcatenate::concatenate);
 
 } /* namespace regexp */
diff --git a/alib2algo/src/regexp/transform/RegExpConcatenate.h b/alib2algo/src/regexp/transform/RegExpConcatenate.h
index 1aa84804400395c6d6b34c55b22baeb4028727c5..6738703a3e9d724275499692bb76832d213a4808 100644
--- a/alib2algo/src/regexp/transform/RegExpConcatenate.h
+++ b/alib2algo/src/regexp/transform/RegExpConcatenate.h
@@ -20,7 +20,7 @@ namespace regexp {
  * Concatenates two regexpses
  *
  */
-class RegExpConcatenate : public std::DoubleDispatch<regexp::RegExp, regexp::RegExpBase, regexp::RegExpBase> {
+class RegExpConcatenate : public std::PromotingDoubleDispatch<regexp::RegExp, regexp::RegExpBase> {
 public:
 	static regexp::RegExp concatenate(const regexp::RegExp& first, const regexp::RegExp& second);
 
diff --git a/alib2algo/src/stringology/exact/ExactFactorMatch.cpp b/alib2algo/src/stringology/exact/ExactFactorMatch.cpp
index 2c79217bdfb8196218fcf261b6090d6884617a8e..556983b527e6d74e9f3b616ace57fcb24a007c10 100644
--- a/alib2algo/src/stringology/exact/ExactFactorMatch.cpp
+++ b/alib2algo/src/stringology/exact/ExactFactorMatch.cpp
@@ -33,7 +33,7 @@ std::set<unsigned> ExactFactorMatch::match(const string::LinearString& subject,
 	return occ;
 }
 
-auto ExactFactorMatchLinearStringLinearString = ExactFactorMatch::RegistratorWrapper<std::set<unsigned>, string::LinearString, string::LinearString>(ExactFactorMatch::getInstance(), ExactFactorMatch::match);
+auto ExactFactorMatchLinearString = ExactFactorMatch::RegistratorWrapper<std::set<unsigned>, string::LinearString>(ExactFactorMatch::getInstance(), ExactFactorMatch::match);
 
 } /* namespace exact */
 
diff --git a/alib2algo/src/stringology/exact/ExactFactorMatch.h b/alib2algo/src/stringology/exact/ExactFactorMatch.h
index 451ac76e3d277d617290a491054724d3161aac02..7cde576a171b1b2b78a5d5b3439692ad90d8fc8f 100644
--- a/alib2algo/src/stringology/exact/ExactFactorMatch.h
+++ b/alib2algo/src/stringology/exact/ExactFactorMatch.h
@@ -17,7 +17,7 @@ namespace stringology {
 
 namespace exact {
 
-class ExactFactorMatch : public std::DoubleDispatch<std::set<unsigned>, string::StringBase, string::StringBase> {
+class ExactFactorMatch : public std::PromotingDoubleDispatch<std::set<unsigned>, string::StringBase> {
 public:
 	/**
 	 * Performs conversion.
diff --git a/alib2algo/test-src/regexp/transform/RegExpConcatenateTest.cpp b/alib2algo/test-src/regexp/transform/RegExpConcatenateTest.cpp
index 9479a1e7cb042fed01a7aa5e2a82f39915a6b506..d50d8d40798cb92b15518dfc75e0d80c9509ee4a 100644
--- a/alib2algo/test-src/regexp/transform/RegExpConcatenateTest.cpp
+++ b/alib2algo/test-src/regexp/transform/RegExpConcatenateTest.cpp
@@ -31,7 +31,7 @@ void RegExpConcatenateTest::testRegExpConcatenate() {
 
 		CPPUNIT_ASSERT(re == rer);
 	}
-	/*{ TODO reenable when promoting multiple dispatch is ready
+	{
 		std::string input1 = "(#E a b)";
 		regexp::RegExp re1 = alib::StringDataFactory::fromString<regexp::RegExp>(input1);
 
@@ -62,5 +62,5 @@ void RegExpConcatenateTest::testRegExpConcatenate() {
 		std::cout << re << std::endl;
 		std::cout << rer << std::endl;
 		CPPUNIT_ASSERT(re == rer);
-	}*/
+	}
 }
diff --git a/alib2data/src/CastApi.hpp b/alib2data/src/CastApi.hpp
index 93fa69286f69a9d30074866db9c956da0258b660..dc6b942c19aa288ad73932eb9047e931989817b8 100644
--- a/alib2data/src/CastApi.hpp
+++ b/alib2data/src/CastApi.hpp
@@ -29,6 +29,10 @@ struct castApi {
 				throw std::bad_cast();
 			return res->second(from);
 		}
+
+		bool castAvailable(long long from) {
+			return castFunctions.count(from);
+		}
 	};
 
 	template<class To>
@@ -40,6 +44,11 @@ struct castApi {
 			castFunctions.insert(std::make_pair(From::typeId((const From&) a), [](const alib::ObjectBase& from) { return alib::Object(To((const From&) from)); } ));
 		}
 
+		template<class From>
+		bool test() {
+			int a = 0;
+			return castFunctions.count(From::typeId((const From&) a));
+		}
 	};
 
 private:
@@ -78,6 +87,22 @@ public:
 		}
 	}
 
+	static CastPoolBase& getCastPool(long long typeId) {
+		std::map<long long, CastPoolBase*>::iterator res = castFunctionsById().find(typeId);
+		if(res == castFunctionsById().end()) {
+			throw std::invalid_argument("Casting to type ? not available.");
+		} else {
+			return * res->second;
+		}
+	}
+
+	static bool castAvailable(long long to, long long from) {
+		std::map<long long, CastPoolBase*>::iterator res = castFunctionsById().find(to);
+		if(res == castFunctionsById().end())
+			return false;
+		return res->second->castAvailable(from);
+	}
+
 	template<class To>
 	class CastPoolStringBinder {
 	public:
diff --git a/alib2data/src/common/multipleDispatch.hpp b/alib2data/src/common/multipleDispatch.hpp
index 5d7760807f6372ceb5bc56f8ffb22f7d1b7cabe7..ccf5879535e984dc42db00fe12dc31fab74b811d 100644
--- a/alib2data/src/common/multipleDispatch.hpp
+++ b/alib2data/src/common/multipleDispatch.hpp
@@ -13,6 +13,8 @@
 #include <map>
 #include <iostream>
 
+#include "../CastApi.hpp"
+
 namespace std {
 
 template<class ReturnType, class FirstParameterType>
@@ -131,6 +133,63 @@ public:
 
 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
+template<class ReturnType, class ParametersType>
+class PromotingDoubleDispatch {
+public:
+	class RegistratorWrapperBase {
+	public:
+		virtual ReturnType eval(bool firstAttempt, const ParametersType&, const ParametersType&) = 0;
+		virtual bool available(bool firstAttempt, long long first, long long second) = 0;
+	};
+
+private:
+	typedef PromotingDoubleDispatch<ReturnType, ParametersType> SelfType;
+
+	std::map<long long, typename SelfType::RegistratorWrapperBase*> registeredFunctions;
+
+public:
+	template<class RealReturnType, class RealParametersType>
+	class RegistratorWrapper : public RegistratorWrapperBase {
+		std::function<RealReturnType(const RealParametersType&, const RealParametersType&)> callback;
+
+	public:
+		ReturnType eval(bool firstAttempt, const ParametersType& first, const ParametersType& second) {
+			if(firstAttempt) {
+				alib::Object casted = alib::castApi::getCastPool(first.selfTypeId()).cast(second);
+				return ReturnType(callback((const RealParametersType&) first, (const RealParametersType&) casted.getData()));
+			} else {
+				alib::Object casted = alib::castApi::getCastPool(first.selfTypeId()).cast(first);
+				return ReturnType(callback((const RealParametersType&) casted.getData(), (const RealParametersType&) second));
+			}
+		}
+
+		bool available(bool firstAttempt, long long first, long long second) {
+			if(firstAttempt)
+				return alib::castApi::castAvailable(first, second);
+			else
+				return alib::castApi::castAvailable(second, first);
+		}
+
+		RegistratorWrapper(SelfType& pool, RealReturnType(*callback)(const RealParametersType&, const RealParametersType&)) : callback(callback) {
+			int a = 0;
+			pool.registeredFunctions.insert(std::make_pair(RealParametersType::typeId((const RealParametersType&) a), this));
+		}
+	};
+
+	ReturnType dispatch(const ParametersType& first, const ParametersType& second) {
+		typename std::map<long long, RegistratorWrapperBase*>::iterator callback = registeredFunctions.find(first.selfTypeId());
+		if(callback != registeredFunctions.end() && callback->second->available(true, first.selfTypeId(), second.selfTypeId())) return callback->second->eval(true, first, second);
+
+		callback = registeredFunctions.find(second.selfTypeId());
+		if(callback != registeredFunctions.end() && callback->second->available(false, first.selfTypeId(), second.selfTypeId())) return callback->second->eval(false, first, second);
+
+		throw std::bad_function_call();
+	}
+
+};
+
+// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
 template<class ReturnType, class FirstParameterType, class SecondParameterType>
 class DoubleDispatch {
 public: