From 876d97e9c767fbfffdabfdb3b8fd0e99e9fb67a0 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Wed, 12 Aug 2015 23:01:01 +0200 Subject: [PATCH] promoting double dispatch using castApi --- .../src/arbology/exact/ExactSubtreeMatch.cpp | 8 +-- .../src/arbology/exact/ExactSubtreeMatch.h | 2 +- .../src/regexp/transform/RegExpAlternate.cpp | 4 +- .../src/regexp/transform/RegExpAlternate.h | 2 +- .../regexp/transform/RegExpConcatenate.cpp | 4 +- .../src/regexp/transform/RegExpConcatenate.h | 2 +- .../stringology/exact/ExactFactorMatch.cpp | 2 +- .../src/stringology/exact/ExactFactorMatch.h | 2 +- .../transform/RegExpConcatenateTest.cpp | 4 +- alib2data/src/CastApi.hpp | 25 ++++++++ alib2data/src/common/multipleDispatch.hpp | 59 +++++++++++++++++++ 11 files changed, 99 insertions(+), 15 deletions(-) diff --git a/alib2algo/src/arbology/exact/ExactSubtreeMatch.cpp b/alib2algo/src/arbology/exact/ExactSubtreeMatch.cpp index 08b61e361d..f711c038fe 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 ee63da8750..c596fd0419 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 75748fda86..5824eab640 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 fda432cce9..b915c1b9f8 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 514baf7d1a..ddb89264b2 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 1aa8480440..6738703a3e 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 2c79217bdf..556983b527 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 451ac76e3d..7cde576a17 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 9479a1e7cb..d50d8d4079 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 93fa69286f..dc6b942c19 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 5d7760807f..ccf5879535 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: -- GitLab