diff --git a/alib2algo/src/automaton/run/Accept.cpp b/alib2algo/src/automaton/run/Accept.cpp
index f594e91070360ec4b962fa7187f2631eab738d37..8dd9ad780c21bf6f8808e9f8f80a45ad542f2e64 100644
--- a/alib2algo/src/automaton/run/Accept.cpp
+++ b/alib2algo/src/automaton/run/Accept.cpp
@@ -20,23 +20,15 @@ namespace automaton {
 namespace run {
 
 bool Accept::accept(const automaton::Automaton& automaton, const alib::Object& object) {
-	std::pair<const alib::Object*, bool> data(&object, false);
-	automaton.getData().Accept((void*) &data, Accept::ACCEPT);
-	return data.second;
+	return getInstance().dispatch(automaton.getData(), object.getData());
 }
 
 bool Accept::accept(const automaton::Automaton& automaton, const string::LinearString& string) {
-	alib::Object obj(string);
-	std::pair<const alib::Object*, bool> data(&obj, false);
-	automaton.getData().Accept((void*) &data, Accept::ACCEPT);
-	return data.second;
+	return getInstance().dispatch(automaton.getData(), string);
 }
 
 bool Accept::accept(const automaton::Automaton& automaton, const tree::RankedTree& tree) {
-	alib::Object obj(tree);
-	std::pair<const alib::Object*, bool> data(&obj, false);
-	automaton.getData().Accept((void*) &data, Accept::ACCEPT);
-	return data.second;
+	return getInstance().dispatch(automaton.getData(), tree);
 }
 
 bool Accept::accept(const automaton::DFA& automaton, const string::LinearString& string) {
@@ -50,6 +42,8 @@ bool Accept::accept(const automaton::DFA& automaton, const string::LinearString&
 	return automaton.getFinalStates().count(state);
 }
 
+auto AcceptDFALinearString = Accept::RegistratorWrapper<bool, automaton::DFA, string::LinearString>(Accept::getInstance(), Accept::accept);
+
 State Accept::calculateState(const automaton::DFTA& automaton, const tree::RankedNode & node) {
 	std::vector<State> states;
 	states.reserve(node.getSymbol().getRank().getData());
@@ -67,6 +61,8 @@ bool Accept::accept(const automaton::DFTA& automaton, const tree::RankedTree& tr
 	return automaton.getFinalStates().count(calculateState(automaton, tree.getRoot()));
 }
 
+auto AcceptDFTARankedTree = Accept::RegistratorWrapper<bool, automaton::DFTA, tree::RankedTree>(Accept::getInstance(), Accept::accept);
+
 std::set<State> calculateStates(const automaton::NFTA& automaton, const tree::RankedNode & node) {
 	std::vector<std::set<State> > states;
 	states.reserve(node.getSymbol().getRank().getData());
@@ -95,6 +91,8 @@ bool Accept::accept(const automaton::NFTA& automaton, const tree::RankedTree & t
 	return false;
 }
 
+auto AcceptNFTARankedTree = Accept::RegistratorWrapper<bool, automaton::NFTA, tree::RankedTree>(Accept::getInstance(), Accept::accept);
+
 bool recursiveAccept(const automaton::NFA& automaton, const automaton::State& state, const string::LinearString& string) {
 	if( string.getContent().empty( ) )
 		return automaton.getFinalStates().count( state );
@@ -115,6 +113,8 @@ bool Accept::accept( const automaton::NFA& automaton, const string::LinearString
 	return recursiveAccept(automaton, automaton.getInitialState(), string);
 }
 
+auto AcceptNFALinearString = Accept::RegistratorWrapper<bool, automaton::NFA, string::LinearString>(Accept::getInstance(), Accept::accept);
+
 bool Accept::accept(const automaton::DPDA& automaton, const string::LinearString& string) {
 	automaton::State state = automaton.getInitialState();
 	std::deque<alphabet::Symbol> pushdownStore;
@@ -153,88 +153,7 @@ bool Accept::accept(const automaton::DPDA& automaton, const string::LinearString
 	}
 }
 
-void Accept::Visit(void*, const automaton::EpsilonNFA& ) const {
-	throw exception::AlibException("Unsupported automaton type EpsilonNFA");
-}
-
-void Accept::Visit(void*, const automaton::MultiInitialStateNFA& ) const {
-	throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA");
-}
-
-void Accept::Visit(void* data, const automaton::NFA& automaton) const {
-	std::pair<const alib::Object*, bool> & res = *((std::pair<const alib::Object*, bool>*) data);
-	res.second = this->accept(automaton, static_cast<const string::LinearString&>(res.first->getData()));
-}
-
-void Accept::Visit(void* data, const automaton::DFA& automaton) const {
-	std::pair<const alib::Object*, bool> & res = *((std::pair<const alib::Object*, bool>*) data);
-	res.second = this->accept(automaton, static_cast<const string::LinearString&>(res.first->getData()));
-}
-
-void Accept::Visit(void*, const automaton::ExtendedNFA& ) const {
-	throw exception::AlibException("Unsupported automaton type ExtendedNFA");
-}
-
-void Accept::Visit(void*, const automaton::CompactNFA& ) const {
-	throw exception::AlibException("Unsupported automaton type CompactNFA");
-}
-
-void Accept::Visit(void* data, const DPDA& automaton) const {
-	std::pair<const alib::Object*, bool> & res = *((std::pair<const alib::Object*, bool>*) data);
-	res.second = this->accept(automaton, static_cast<const string::LinearString&>(res.first->getData()));
-}
-
-void Accept::Visit(void*, const SinglePopDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
-}
-
-void Accept::Visit(void*, const InputDrivenDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type InputDrivenDPDA");
-}
-
-void Accept::Visit(void*, const InputDrivenNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
-}
-
-void Accept::Visit(void*, const VisiblyPushdownDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA");
-}
-
-void Accept::Visit(void*, const VisiblyPushdownNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
-}
-
-void Accept::Visit(void*, const RealTimeHeightDeterministicDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA");
-}
-
-void Accept::Visit(void*, const RealTimeHeightDeterministicNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA");
-}
-
-void Accept::Visit(void*, const NPDA&) const {
-	throw exception::AlibException("Unsupported automaton type NPDA");
-}
-
-void Accept::Visit(void*, const SinglePopNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
-}
-
-void Accept::Visit(void*, const OneTapeDTM&) const {
-	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
-}
-
-void Accept::Visit(void* data, const automaton::DFTA& automaton) const {
-	std::pair<const alib::Object*, bool> & res = *((std::pair<const alib::Object*, bool>*) data);
-	res.second = this->accept(automaton, static_cast<const tree::RankedTree&>(res.first->getData()));
-}
-
-void Accept::Visit(void* data, const NFTA& automaton) const {
-	std::pair<const alib::Object*, bool> & res = *((std::pair<const alib::Object*, bool>*) data);
-	res.second = this->accept(automaton, static_cast<const tree::RankedTree&>(res.first->getData()));
-}
-
-const Accept Accept::ACCEPT;
+auto AcceptDPDALinearString = Accept::RegistratorWrapper<bool, automaton::DPDA, string::LinearString>(Accept::getInstance(), Accept::accept);
 
 } /* namespace run */
 
diff --git a/alib2algo/src/automaton/run/Accept.h b/alib2algo/src/automaton/run/Accept.h
index 119c85912597466d04d69985f0ff5a780e5eb20c..b4293ecc6f72937c44d79452262168e3e7954602 100644
--- a/alib2algo/src/automaton/run/Accept.h
+++ b/alib2algo/src/automaton/run/Accept.h
@@ -8,6 +8,7 @@
 #ifndef _AUTOMATON_ACCEPT_H__
 #define _AUTOMATON_ACCEPT_H__
 
+#include <common/multipleDispatch.hpp>
 #include <automaton/Automaton.h>
 #include <object/Object.h>
 #include <string/LinearString.h>
@@ -17,10 +18,8 @@ namespace automaton {
 
 namespace run {
 
-class Accept : public automaton::VisitableAutomatonBase::const_visitor_type {
+class Accept : public std::DoubleDispatch<bool, automaton::AutomatonBase, alib::ObjectBase> {
 public:
-	Accept() {}
-
 	/**
 	 * Performs conversion.
 	 * @return left regular grammar equivalent to source automaton.
@@ -37,27 +36,11 @@ public:
 private:
 	static State calculateState(const automaton::DFTA& automaton, const tree::RankedNode & node);
 
-	void Visit(void*, const EpsilonNFA& automaton) const;
-	void Visit(void*, const MultiInitialStateNFA& automaton) const;
-	void Visit(void*, const NFA& automaton) const;
-	void Visit(void*, const DFA& automaton) const;
-	void Visit(void*, const ExtendedNFA& automaton) const;
-	void Visit(void*, const CompactNFA& automaton) const;
-	void Visit(void*, const DPDA& automaton) const;
-	void Visit(void*, const SinglePopDPDA& automaton) const;
-	void Visit(void*, const InputDrivenDPDA& automaton) const;
-	void Visit(void*, const InputDrivenNPDA& automaton) const;
-	void Visit(void*, const VisiblyPushdownDPDA& automaton) const;
-	void Visit(void*, const VisiblyPushdownNPDA& automaton) const;
-	void Visit(void*, const RealTimeHeightDeterministicDPDA& automaton) const;
-	void Visit(void*, const RealTimeHeightDeterministicNPDA& automaton) const;
-	void Visit(void*, const NPDA& automaton) const;
-	void Visit(void*, const SinglePopNPDA& automaton) const;
-	void Visit(void*, const OneTapeDTM& automaton) const;
-	void Visit(void*, const DFTA& automaton) const;
-	void Visit(void*, const NFTA& automaton) const;
-
-	static const Accept ACCEPT;
+public:
+	static Accept& getInstance() {
+		static Accept res;
+		return res;
+	}
 };
 
 } /* namespace run */
diff --git a/alib2algo/src/automaton/run/Occurrences.cpp b/alib2algo/src/automaton/run/Occurrences.cpp
index a07b512feb40b3e08ffc979dc00774149c54e4a3..1dd72424c58b7f94f9cf5b33fe5575f7b1d02b74 100644
--- a/alib2algo/src/automaton/run/Occurrences.cpp
+++ b/alib2algo/src/automaton/run/Occurrences.cpp
@@ -19,23 +19,15 @@ namespace automaton {
 namespace run {
 
 std::set<unsigned> Occurrences::occurrences(const automaton::Automaton& automaton, const alib::Object& object) {
-	std::pair<const alib::Object*, std::set<unsigned>> data(&object, {});
-	automaton.getData().Accept((void*) &data, Occurrences::OCCURRENCES);
-	return data.second;
+	return getInstance().dispatch(automaton.getData(), object.getData());
 }
 
 std::set<unsigned> Occurrences::occurrences(const automaton::Automaton& automaton, const string::LinearString& string) {
-	alib::Object obj(string);
-	std::pair<const alib::Object*, std::set<unsigned>> data(&obj, {});
-	automaton.getData().Accept((void*) &data, Occurrences::OCCURRENCES);
-	return data.second;
+	return getInstance().dispatch(automaton.getData(), string);
 }
 
 std::set<unsigned> Occurrences::occurrences(const automaton::Automaton& automaton, const tree::RankedTree& tree) {
-	alib::Object obj(tree);
-	std::pair<const alib::Object*, std::set<unsigned>> data(&obj, {});
-	automaton.getData().Accept((void*) &data, Occurrences::OCCURRENCES);
-	return data.second;
+	return getInstance().dispatch(automaton.getData(), tree);
 }
 
 std::set<unsigned> Occurrences::occurrences(const automaton::DFA& automaton, const string::LinearString& string) {
@@ -64,14 +56,16 @@ std::set<unsigned> Occurrences::occurrences(const automaton::DFA& automaton, con
 	return occ;
 }
 
-State Occurrences::occurences(const automaton::DFTA & automaton, const tree::RankedNode & node, std::set<unsigned> & occ, unsigned & i) {
+auto OccurrencesDFALinearString = Occurrences::RegistratorWrapper<std::set<unsigned>, automaton::DFA, string::LinearString>(Occurrences::getInstance(), Occurrences::occurrences);
+
+State Occurrences::occurrences(const automaton::DFTA & automaton, const tree::RankedNode & node, std::set<unsigned> & occ, unsigned & i) {
 	std::vector<State> states;
 	unsigned tmp = i;
 	i++;
 	states.reserve(node.getSymbol().getRank().getData());
 	bool fail = false;
 	for (const auto & child : node.getChildren()) {
-		State state = occurences(automaton, *child, occ, i);
+		State state = occurrences(automaton, *child, occ, i);
 		if (state == FAILSTATE) fail = true;
 		else if (!fail) states.push_back(state);
 	}
@@ -86,10 +80,12 @@ State Occurrences::occurences(const automaton::DFTA & automaton, const tree::Ran
 std::set<unsigned> Occurrences::occurrences(const automaton::DFTA& automaton, const tree::RankedTree & tree) {
 	std::set<unsigned> occ;
 	unsigned i = 0;
-	occurences(automaton, tree.getRoot(), occ, i);
+	occurrences(automaton, tree.getRoot(), occ, i);
 	return occ;
 }
 
+auto OccurrencesDFTARankedTree = Occurrences::RegistratorWrapper<std::set<unsigned>, automaton::DFTA, tree::RankedTree>(Occurrences::getInstance(), Occurrences::occurrences);
+
 std::set<unsigned> Occurrences::occurrences(const automaton::DPDA& automaton, const string::LinearString& string) {
 	automaton::State state = automaton.getInitialState();
 	std::deque<alphabet::Symbol> pushdownStore;
@@ -139,86 +135,7 @@ std::set<unsigned> Occurrences::occurrences(const automaton::DPDA& automaton, co
 	}
 }
 
-void Occurrences::Visit(void*, const automaton::EpsilonNFA& ) const {
-	throw exception::AlibException("Unsupported automaton type EpsilonNFA");
-}
-
-void Occurrences::Visit(void*, const automaton::MultiInitialStateNFA& ) const {
-	throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA");
-}
-
-void Occurrences::Visit(void*, const automaton::NFA& ) const {
-	throw exception::AlibException("NFA");
-}
-
-void Occurrences::Visit(void* data, const automaton::DFA& automaton) const {
-	std::pair<const alib::Object*, std::set<unsigned>> & res = *((std::pair<const alib::Object*, std::set<unsigned>>*) data);
-	res.second = this->occurrences(automaton, static_cast<const string::LinearString&>(res.first->getData()));
-}
-
-void Occurrences::Visit(void*, const automaton::ExtendedNFA& ) const {
-	throw exception::AlibException("Unsupported automaton type ExtendedNFA");
-}
-
-void Occurrences::Visit(void*, const automaton::CompactNFA& ) const {
-	throw exception::AlibException("Unsupported automaton type CompactNFA");
-}
-
-void Occurrences::Visit(void* data, const DPDA& automaton) const {
-	std::pair<const alib::Object*, std::set<unsigned>> & res = *((std::pair<const alib::Object*, std::set<unsigned>>*) data);
-	res.second = this->occurrences(automaton, static_cast<const string::LinearString&>(res.first->getData()));
-}
-
-void Occurrences::Visit(void*, const SinglePopDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
-}
-
-void Occurrences::Visit(void*, const InputDrivenDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type InputDrivenDPDA");
-}
-
-void Occurrences::Visit(void*, const InputDrivenNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
-}
-
-void Occurrences::Visit(void*, const VisiblyPushdownDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA");
-}
-
-void Occurrences::Visit(void*, const VisiblyPushdownNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
-}
-
-void Occurrences::Visit(void*, const RealTimeHeightDeterministicDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA");
-}
-
-void Occurrences::Visit(void*, const RealTimeHeightDeterministicNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA");
-}
-
-void Occurrences::Visit(void*, const NPDA&) const {
-	throw exception::AlibException("Unsupported automaton type NPDA");
-}
-
-void Occurrences::Visit(void*, const SinglePopNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
-}
-
-void Occurrences::Visit(void*, const OneTapeDTM&) const {
-	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
-}
-
-void Occurrences::Visit(void* data, const automaton::DFTA& automaton) const {
-	std::pair<const alib::Object*, std::set<unsigned>> & res = *((std::pair<const alib::Object*, std::set<unsigned>>*) data);
-	res.second = this->occurrences(automaton, static_cast<const tree::RankedTree&>(res.first->getData()));
-}
-
-void Occurrences::Visit(void*, const NFTA&) const {
-	throw exception::AlibException("Unsupported automaton type NFTA");
-}
-
-const Occurrences Occurrences::OCCURRENCES;
+auto OccurrencesDPDALinearString = Occurrences::RegistratorWrapper<std::set<unsigned>, automaton::DPDA, string::LinearString>(Occurrences::getInstance(), Occurrences::occurrences);
 
 } /* namespace run */
 
diff --git a/alib2algo/src/automaton/run/Occurrences.h b/alib2algo/src/automaton/run/Occurrences.h
index b5cba0c4e5bd0b74d849296923a42e4f457e7a6a..d04dd10fe78bd37d1018cc5b99dc45e3550a08f3 100644
--- a/alib2algo/src/automaton/run/Occurrences.h
+++ b/alib2algo/src/automaton/run/Occurrences.h
@@ -8,6 +8,7 @@
 #ifndef _AUTOMATON_OCCURRENCES_H__
 #define _AUTOMATON_OCCURRENCES_H__
 
+#include <common/multipleDispatch.hpp>
 #include <automaton/Automaton.h>
 #include <object/Object.h>
 #include <string/LinearString.h>
@@ -17,10 +18,8 @@ namespace automaton {
 
 namespace run {
 
-class Occurrences : public automaton::VisitableAutomatonBase::const_visitor_type {
+class Occurrences : public std::DoubleDispatch<std::set<unsigned>, automaton::AutomatonBase, alib::ObjectBase> {
 public:
-	Occurrences() {}
-
 	/**
 	 * Performs conversion.
 	 * @return left regular grammar equivalent to source automaton.
@@ -33,29 +32,13 @@ public:
 	static std::set<unsigned> occurrences(const automaton::DPDA& automaton, const string::LinearString& string);
 	static std::set<unsigned> occurrences(const automaton::DFTA& automaton, const tree::RankedTree & tree);
 private:
-	static State occurences(const automaton::DFTA & automaton, const tree::RankedNode & node, std::set<unsigned> & occ, unsigned & i);
-
-	void Visit(void*, const EpsilonNFA& automaton) const;
-	void Visit(void*, const MultiInitialStateNFA& automaton) const;
-	void Visit(void*, const NFA& automaton) const;
-	void Visit(void*, const DFA& automaton) const;
-	void Visit(void*, const ExtendedNFA& automaton) const;
-	void Visit(void*, const CompactNFA& automaton) const;
-	void Visit(void*, const DPDA& automaton) const;
-	void Visit(void*, const SinglePopDPDA& automaton) const;
-	void Visit(void*, const InputDrivenDPDA& automaton) const;
-	void Visit(void*, const InputDrivenNPDA& automaton) const;
-	void Visit(void*, const VisiblyPushdownDPDA& automaton) const;
-	void Visit(void*, const VisiblyPushdownNPDA& automaton) const;
-	void Visit(void*, const RealTimeHeightDeterministicDPDA& automaton) const;
-	void Visit(void*, const RealTimeHeightDeterministicNPDA& automaton) const;
-	void Visit(void*, const NPDA& automaton) const;
-	void Visit(void*, const SinglePopNPDA& automaton) const;
-	void Visit(void*, const OneTapeDTM& automaton) const;
-	void Visit(void*, const DFTA& automaton) const;
-	void Visit(void*, const NFTA& automaton) const;
+	static State occurrences(const automaton::DFTA & automaton, const tree::RankedNode & node, std::set<unsigned> & occ, unsigned & i);
 
-	static const Occurrences OCCURRENCES;
+public:
+	static Occurrences& getInstance() {
+		static Occurrences res;
+		return res;
+	}
 };
 
 } /* namespace run */
diff --git a/alib2algo/src/automaton/run/Result.cpp b/alib2algo/src/automaton/run/Result.cpp
index 0194f931c5958dbf6b7548a4cc425ef053ad9b9c..6c6e47617954521389b85487e526c0da3bff14f1 100644
--- a/alib2algo/src/automaton/run/Result.cpp
+++ b/alib2algo/src/automaton/run/Result.cpp
@@ -19,11 +19,7 @@ namespace automaton {
 namespace run {
 
 label::Label Result::result(const automaton::Automaton& automaton, const alib::Object& object) {
-	std::pair<const alib::Object*, label::Label*> data(&object, NULL);
-	automaton.getData().Accept((void*) &data, Result::RESULT);
-	label::Label res = std::move(*data.second);
-	delete data.second;
-	return res;
+	return getInstance().dispatch(automaton.getData(), object.getData());
 }
 
 label::Label Result::result(const automaton::DFA& automaton, const string::LinearString& string) {
@@ -37,6 +33,8 @@ label::Label Result::result(const automaton::DFA& automaton, const string::Linea
 	return state.getName();
 }
 
+auto ResultDFALinearString = Result::RegistratorWrapper<label::Label, automaton::DFA, string::LinearString>(Result::getInstance(), Result::result);
+
 label::Label Result::result(const automaton::DPDA& automaton, const string::LinearString& string) {
 	automaton::State state = automaton.getInitialState();
 	std::deque<alphabet::Symbol> pushdownStore;
@@ -75,6 +73,8 @@ label::Label Result::result(const automaton::DPDA& automaton, const string::Line
 	}
 }
 
+auto ResultDPDALinearString = Result::RegistratorWrapper<label::Label, automaton::DPDA, string::LinearString>(Result::getInstance(), Result::result);
+
 automaton::State Result::calculateState(const automaton::DFTA& automaton, const tree::RankedNode & node) {
 	std::vector<automaton::State> states;
 	states.reserve(node.getSymbol().getRank().getData());
@@ -93,86 +93,7 @@ label::Label Result::result(const automaton::DFTA& automaton, const tree::Ranked
 	return state.getName();
 }
 
-void Result::Visit(void*, const automaton::EpsilonNFA& ) const {
-	throw exception::AlibException("Unsupported automaton type EpsilonNFA");
-}
-
-void Result::Visit(void*, const automaton::MultiInitialStateNFA& ) const {
-	throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA");
-}
-
-void Result::Visit(void*, const automaton::NFA& ) const {
-	throw exception::AlibException("Unsupported automaton type NFA");
-}
-
-void Result::Visit(void* data, const automaton::DFA& automaton) const {
-	std::pair<const alib::Object*, label::Label*> & res = *((std::pair<const alib::Object*,  label::Label*>*) data);
-	res.second = new label::Label(std::move(this->result(automaton, static_cast<const string::LinearString&>(res.first->getData()))));
-}
-
-void Result::Visit(void*, const automaton::ExtendedNFA& ) const {
-	throw exception::AlibException("Unsupported automaton type ExtendedNFA");
-}
-
-void Result::Visit(void*, const automaton::CompactNFA& ) const {
-	throw exception::AlibException("Unsupported automaton type CompactNFA");
-}
-
-void Result::Visit(void* data, const DPDA& automaton) const {
-	std::pair<const alib::Object*, label::Label*> & res = *((std::pair<const alib::Object*,  label::Label*>*) data);
-	res.second = new label::Label(std::move(this->result(automaton, static_cast<const string::LinearString&>(res.first->getData()))));
-}
-
-void Result::Visit(void*, const SinglePopDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
-}
-
-void Result::Visit(void*, const InputDrivenDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type InputDrivenDPDA");
-}
-
-void Result::Visit(void*, const InputDrivenNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
-}
-
-void Result::Visit(void*, const VisiblyPushdownDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA");
-}
-
-void Result::Visit(void*, const VisiblyPushdownNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
-}
-
-void Result::Visit(void*, const RealTimeHeightDeterministicDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA");
-}
-
-void Result::Visit(void*, const RealTimeHeightDeterministicNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA");
-}
-
-void Result::Visit(void*, const NPDA&) const {
-	throw exception::AlibException("Unsupported automaton type NPDA");
-}
-
-void Result::Visit(void*, const SinglePopNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
-}
-
-void Result::Visit(void*, const OneTapeDTM&) const {
-	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
-}
-
-void Result::Visit(void* data, const automaton::DFTA& automaton) const {
-	std::pair<const alib::Object*, label::Label*> & res = *((std::pair<const alib::Object*,  label::Label*>*) data);
-	res.second = new label::Label(std::move(this->result(automaton, static_cast<const tree::RankedTree&>(res.first->getData()))));
-}
-
-void Result::Visit(void*, const NFTA&) const {
-	throw exception::AlibException("Unsupported automaton type NFTA");
-}
-
-const Result Result::RESULT;
+auto ResultDFTARankedTree = Result::RegistratorWrapper<label::Label, automaton::DFTA, tree::RankedTree>(Result::getInstance(), Result::result);
 
 } /* namespace run */
 
diff --git a/alib2algo/src/automaton/run/Result.h b/alib2algo/src/automaton/run/Result.h
index 01144bd00ab252a9940e2e2fe2892bd1b0266ec8..ee4dfe73e4702ae787331e5415f1ad259be1b4a4 100644
--- a/alib2algo/src/automaton/run/Result.h
+++ b/alib2algo/src/automaton/run/Result.h
@@ -8,6 +8,7 @@
 #ifndef _AUTOMATON_RESULT_H__
 #define _AUTOMATON_RESULT_H__
 
+#include <common/multipleDispatch.hpp>
 #include <automaton/Automaton.h>
 #include <string/LinearString.h>
 #include <object/Object.h>
@@ -18,10 +19,8 @@ namespace automaton {
 
 namespace run {
 
-class Result : public automaton::VisitableAutomatonBase::const_visitor_type {
+class Result : public std::DoubleDispatch<label::Label, automaton::AutomatonBase, alib::ObjectBase> {
 public:
-	Result() {}
-
 	/**
 	 * Performs conversion.
 	 * @return left regular grammar equivalent to source automaton.
@@ -34,27 +33,11 @@ public:
 private:
 	static automaton::State calculateState(const automaton::DFTA& automaton, const tree::RankedNode & node);
 
-	void Visit(void*, const EpsilonNFA& automaton) const;
-	void Visit(void*, const MultiInitialStateNFA& automaton) const;
-	void Visit(void*, const NFA& automaton) const;
-	void Visit(void*, const DFA& automaton) const;
-	void Visit(void*, const ExtendedNFA& automaton) const;
-	void Visit(void*, const CompactNFA& automaton) const;
-	void Visit(void*, const DPDA& automaton) const;
-	void Visit(void*, const SinglePopDPDA& automaton) const;
-	void Visit(void*, const InputDrivenDPDA& automaton) const;
-	void Visit(void*, const InputDrivenNPDA& automaton) const;
-	void Visit(void*, const VisiblyPushdownDPDA& automaton) const;
-	void Visit(void*, const VisiblyPushdownNPDA& automaton) const;
-	void Visit(void*, const RealTimeHeightDeterministicDPDA& automaton) const;
-	void Visit(void*, const RealTimeHeightDeterministicNPDA& automaton) const;
-	void Visit(void*, const NPDA& automaton) const;
-	void Visit(void*, const SinglePopNPDA& automaton) const;
-	void Visit(void*, const OneTapeDTM& automaton) const;
-	void Visit(void*, const DFTA& automaton) const;
-	void Visit(void*, const NFTA& automaton) const;
-
-	static const Result RESULT;
+public:
+	static Result& getInstance() {
+		static Result res;
+		return res;
+	}
 };
 
 } /* namespace run */