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: