diff --git a/acompare2/src/AutomatonCompare.cpp b/acompare2/src/AutomatonCompare.cpp
index 3a685478dbb5ab3cac243290a6914bc8817c7f38..b7720a52fc2f68ad4ec4ee4223e29d9abb530297 100644
--- a/acompare2/src/AutomatonCompare.cpp
+++ b/acompare2/src/AutomatonCompare.cpp
@@ -1184,6 +1184,8 @@ int AutomatonCompare::compare(const automaton::DFA& a, const automaton::DFA& b)
 	}
 }
 
+auto AutomatonCompareDFA = AutomatonCompare::RegistratorWrapper<int, automaton::DFA, automaton::DFA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::NFA& a, const automaton::NFA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1193,6 +1195,8 @@ int AutomatonCompare::compare(const automaton::NFA& a, const automaton::NFA& b)
 	}
 }
 
+auto AutomatonCompareNFA = AutomatonCompare::RegistratorWrapper<int, automaton::NFA, automaton::NFA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::MultiInitialStateNFA& a, const automaton::MultiInitialStateNFA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1202,6 +1206,8 @@ int AutomatonCompare::compare(const automaton::MultiInitialStateNFA& a, const au
 	}
 }
 
+auto AutomatonCompareMultiInitialStateNFA = AutomatonCompare::RegistratorWrapper<int, automaton::MultiInitialStateNFA, automaton::MultiInitialStateNFA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::EpsilonNFA& a, const automaton::EpsilonNFA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1211,6 +1217,8 @@ int AutomatonCompare::compare(const automaton::EpsilonNFA& a, const automaton::E
 	}
 }
 
+auto AutomatonCompareEpsilonNFA = AutomatonCompare::RegistratorWrapper<int, automaton::EpsilonNFA, automaton::EpsilonNFA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::ExtendedNFA& a, const automaton::ExtendedNFA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1220,6 +1228,8 @@ int AutomatonCompare::compare(const automaton::ExtendedNFA& a, const automaton::
 	}
 }
 
+auto AutomatonCompareExtendedNFA = AutomatonCompare::RegistratorWrapper<int, automaton::ExtendedNFA, automaton::ExtendedNFA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::CompactNFA& a, const automaton::CompactNFA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1229,6 +1239,8 @@ int AutomatonCompare::compare(const automaton::CompactNFA& a, const automaton::C
 	}
 }
 
+auto AutomatonCompareCompactNFA = AutomatonCompare::RegistratorWrapper<int, automaton::CompactNFA, automaton::CompactNFA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::DFTA& a, const automaton::DFTA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1238,6 +1250,8 @@ int AutomatonCompare::compare(const automaton::DFTA& a, const automaton::DFTA& b
 	}
 }
 
+auto AutomatonCompareDFTA = AutomatonCompare::RegistratorWrapper<int, automaton::DFTA, automaton::DFTA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::NFTA& a, const automaton::NFTA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1247,6 +1261,8 @@ int AutomatonCompare::compare(const automaton::NFTA& a, const automaton::NFTA& b
 	}
 }
 
+auto AutomatonCompareNFTA = AutomatonCompare::RegistratorWrapper<int, automaton::NFTA, automaton::NFTA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::DPDA& a, const automaton::DPDA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1256,6 +1272,8 @@ int AutomatonCompare::compare(const automaton::DPDA& a, const automaton::DPDA& b
 	}
 }
 
+auto AutomatonCompareDPDA = AutomatonCompare::RegistratorWrapper<int, automaton::DPDA, automaton::DPDA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::NPDA& a, const automaton::NPDA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1265,6 +1283,8 @@ int AutomatonCompare::compare(const automaton::NPDA& a, const automaton::NPDA& b
 	}
 }
 
+auto AutomatonCompareNPDA = AutomatonCompare::RegistratorWrapper<int, automaton::NPDA, automaton::NPDA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::InputDrivenDPDA& a, const automaton::InputDrivenDPDA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1274,6 +1294,8 @@ int AutomatonCompare::compare(const automaton::InputDrivenDPDA& a, const automat
 	}
 }
 
+auto AutomatonCompareInputDrivenDPDA = AutomatonCompare::RegistratorWrapper<int, automaton::InputDrivenDPDA, automaton::InputDrivenDPDA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::InputDrivenNPDA& a, const automaton::InputDrivenNPDA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1283,6 +1305,8 @@ int AutomatonCompare::compare(const automaton::InputDrivenNPDA& a, const automat
 	}
 }
 
+auto AutomatonCompareInputDrivenNPDA = AutomatonCompare::RegistratorWrapper<int, automaton::InputDrivenNPDA, automaton::InputDrivenNPDA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::VisiblyPushdownDPDA& a, const automaton::VisiblyPushdownDPDA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1292,6 +1316,8 @@ int AutomatonCompare::compare(const automaton::VisiblyPushdownDPDA& a, const aut
 	}
 }
 
+auto AutomatonCompareVisiblyPushdownDPDA = AutomatonCompare::RegistratorWrapper<int, automaton::VisiblyPushdownDPDA, automaton::VisiblyPushdownDPDA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::VisiblyPushdownNPDA& a, const automaton::VisiblyPushdownNPDA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1301,6 +1327,8 @@ int AutomatonCompare::compare(const automaton::VisiblyPushdownNPDA& a, const aut
 	}
 }
 
+auto AutomatonCompareVisiblyPushdownNPDA = AutomatonCompare::RegistratorWrapper<int, automaton::VisiblyPushdownNPDA, automaton::VisiblyPushdownNPDA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::RealTimeHeightDeterministicDPDA& a, const automaton::RealTimeHeightDeterministicDPDA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1310,6 +1338,8 @@ int AutomatonCompare::compare(const automaton::RealTimeHeightDeterministicDPDA&
 	}
 }
 
+auto AutomatonCompareRealTimeHeightDeterministicDPDA = AutomatonCompare::RegistratorWrapper<int, automaton::RealTimeHeightDeterministicDPDA, automaton::RealTimeHeightDeterministicDPDA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::RealTimeHeightDeterministicNPDA& a, const automaton::RealTimeHeightDeterministicNPDA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1319,6 +1349,8 @@ int AutomatonCompare::compare(const automaton::RealTimeHeightDeterministicNPDA&
 	}
 }
 
+auto AutomatonCompareRealTimeHeightDeterministicNPDA = AutomatonCompare::RegistratorWrapper<int, automaton::RealTimeHeightDeterministicNPDA, automaton::RealTimeHeightDeterministicNPDA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::SinglePopDPDA& a, const automaton::SinglePopDPDA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1328,6 +1360,8 @@ int AutomatonCompare::compare(const automaton::SinglePopDPDA& a, const automaton
 	}
 }
 
+auto AutomatonCompareSinglePopDPDA = AutomatonCompare::RegistratorWrapper<int, automaton::SinglePopDPDA, automaton::SinglePopDPDA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::SinglePopNPDA& a, const automaton::SinglePopNPDA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1337,6 +1371,8 @@ int AutomatonCompare::compare(const automaton::SinglePopNPDA& a, const automaton
 	}
 }
 
+auto AutomatonCompareSinglePopNPDA = AutomatonCompare::RegistratorWrapper<int, automaton::SinglePopNPDA, automaton::SinglePopNPDA>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
+
 int AutomatonCompare::compare(const automaton::OneTapeDTM& a, const automaton::OneTapeDTM& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1346,87 +1382,9 @@ int AutomatonCompare::compare(const automaton::OneTapeDTM& a, const automaton::O
 	}
 }
 
-int AutomatonCompare::compare(const automaton::Automaton& a, const automaton::Automaton& b) {
-	int res;
-	Accept((void*) &res, a.getData(), b.getData(), AutomatonCompare::AUTOMATON_COMPARE);
-	return res;
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::CompactNFA& first, const automaton::CompactNFA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::ExtendedNFA& first, const automaton::ExtendedNFA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::MultiInitialStateNFA& first, const automaton::MultiInitialStateNFA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::DFTA& first, const automaton::DFTA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::NFTA& first, const automaton::NFTA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::DPDA& first, const automaton::DPDA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::NPDA& first, const automaton::NPDA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::InputDrivenDPDA& first, const automaton::InputDrivenDPDA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::InputDrivenNPDA& first, const automaton::InputDrivenNPDA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
+auto AutomatonCompareOneTapeDTM = AutomatonCompare::RegistratorWrapper<int, automaton::OneTapeDTM, automaton::OneTapeDTM>(AutomatonCompare::getInstance(), AutomatonCompare::compare);
 
-void AutomatonCompare::Visit(void* data, const automaton::RealTimeHeightDeterministicDPDA& first, const automaton::RealTimeHeightDeterministicDPDA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::RealTimeHeightDeterministicNPDA& first, const automaton::RealTimeHeightDeterministicNPDA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::SinglePopNPDA& first, const automaton::SinglePopNPDA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::SinglePopDPDA& first, const automaton::SinglePopDPDA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::VisiblyPushdownDPDA& first, const automaton::VisiblyPushdownDPDA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::VisiblyPushdownNPDA& first, const automaton::VisiblyPushdownNPDA& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
-}
-
-void AutomatonCompare::Visit(void* data, const automaton::OneTapeDTM& first, const automaton::OneTapeDTM& second) const {
-	*((int*) data) = AutomatonCompare::compare(first, second);
+int AutomatonCompare::compare(const automaton::Automaton& a, const automaton::Automaton& b) {
+	return getInstance().dispatch(a.getData(), b.getData());
 }
 
-const AutomatonCompare AutomatonCompare::AUTOMATON_COMPARE;
-
diff --git a/acompare2/src/AutomatonCompare.h b/acompare2/src/AutomatonCompare.h
index eb3ac08bc1b6c9cc6148624295842893b963c587..f8d568ef03c89273bcb85042ff68f5628c92adba 100644
--- a/acompare2/src/AutomatonCompare.h
+++ b/acompare2/src/AutomatonCompare.h
@@ -8,18 +8,17 @@
 #ifndef AUTOMATON_COMPARE_H_
 #define AUTOMATON_COMPARE_H_
 
+#include <common/multipleDispatch.hpp>
 #include <ostream>
 
 #include <automaton/Automaton.h>
+#include <automaton/AutomatonFeatures.h>
 #include <set>
 #include <list>
 #include <map>
 #include <utility>
 
-class AutomatonCompare : public automaton::VisitableAutomatonBase::const_same_visitor_type {
-public:
-	AutomatonCompare() {}
-
+class AutomatonCompare : public std::DoubleDispatch<int, automaton::AutomatonBase, automaton::AutomatonBase> {
 private:
 	static bool testCompare(const automaton::DFA& a, const automaton::DFA& b);
 	static void printCompare(const automaton::DFA& a, const automaton::DFA& b);
@@ -82,29 +81,6 @@ private:
 	template <class T> static void listCompare(const std::list<T> a, const std::list<T> b);
 	template <class T, class R> static void mapCompare(const std::map<T, R> a, const std::map<T, R> b);
 public:
-	void Visit(void* data, const automaton::CompactNFA& first, const automaton::CompactNFA& second) const;
-	void Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const;
-	void Visit(void* data, const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) const;
-	void Visit(void* data, const automaton::ExtendedNFA& first, const automaton::ExtendedNFA& second) const;
-	void Visit(void* data, const automaton::MultiInitialStateNFA& first, const automaton::MultiInitialStateNFA& second) const;
-	void Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const;
-
-	void Visit(void* data, const automaton::DFTA& first, const automaton::DFTA& second) const;
-	void Visit(void* data, const automaton::NFTA& first, const automaton::NFTA& second) const;
-
-	void Visit(void* data, const automaton::DPDA& first, const automaton::DPDA& second) const;
-	void Visit(void* data, const automaton::NPDA& first, const automaton::NPDA& second) const;
-	void Visit(void* data, const automaton::InputDrivenNPDA& first, const automaton::InputDrivenNPDA& second) const;
-	void Visit(void* data, const automaton::InputDrivenDPDA& first, const automaton::InputDrivenDPDA& second) const;
-	void Visit(void* data, const automaton::RealTimeHeightDeterministicDPDA& first, const automaton::RealTimeHeightDeterministicDPDA& second) const;
-	void Visit(void* data, const automaton::RealTimeHeightDeterministicNPDA& first, const automaton::RealTimeHeightDeterministicNPDA& second) const;
-	void Visit(void* data, const automaton::SinglePopNPDA& first, const automaton::SinglePopNPDA& second) const;
-	void Visit(void* data, const automaton::SinglePopDPDA& first, const automaton::SinglePopDPDA& second) const;
-	void Visit(void* data, const automaton::VisiblyPushdownDPDA& first, const automaton::VisiblyPushdownDPDA& second) const;
-	void Visit(void* data, const automaton::VisiblyPushdownNPDA& first, const automaton::VisiblyPushdownNPDA& second) const;
-
-	void Visit(void* data, const automaton::OneTapeDTM& first, const automaton::OneTapeDTM& second) const;
-
 	static int compare(const automaton::DFA& a, const automaton::DFA& b);
 	static int compare(const automaton::NFA& a, const automaton::NFA& b);
 	static int compare(const automaton::MultiInitialStateNFA& a, const automaton::MultiInitialStateNFA& b);
@@ -130,7 +106,10 @@ public:
 
 	static int compare(const automaton::Automaton& a, const automaton::Automaton& b);
 
-	static const AutomatonCompare AUTOMATON_COMPARE;
+	static AutomatonCompare& getInstance() {
+		static AutomatonCompare res;
+		return res;
+	}
 };
 
 #endif /* AUTOMATON_COMPARE_H_ */
diff --git a/acompare2/src/GrammarCompare.cpp b/acompare2/src/GrammarCompare.cpp
index d290b68b072bc535f10e2d9b874b0fffc2e9d231..cc8f6d3f3227bb90c5255c8d3ec300bcc8011d9a 100644
--- a/acompare2/src/GrammarCompare.cpp
+++ b/acompare2/src/GrammarCompare.cpp
@@ -570,6 +570,8 @@ int GrammarCompare::compare(const grammar::LeftLG& a, const grammar::LeftLG& b)
 	}
 }
 
+auto GrammarCompareLeftLG = GrammarCompare::RegistratorWrapper<int, grammar::LeftLG, grammar::LeftLG>(GrammarCompare::getInstance(), GrammarCompare::compare);
+
 int GrammarCompare::compare(const grammar::LeftRG& a, const grammar::LeftRG& b) {
 	if(!GrammarCompare::testCompare(a, b)) {
 	  GrammarCompare::printCompare(a, b);
@@ -579,6 +581,8 @@ int GrammarCompare::compare(const grammar::LeftRG& a, const grammar::LeftRG& b)
 	}
 }
 
+auto GrammarCompareLeftRG = GrammarCompare::RegistratorWrapper<int, grammar::LeftRG, grammar::LeftRG>(GrammarCompare::getInstance(), GrammarCompare::compare);
+
 int GrammarCompare::compare(const grammar::RightLG& a, const grammar::RightLG& b) {
 	if(!GrammarCompare::testCompare(a, b)) {
 	  GrammarCompare::printCompare(a, b);
@@ -588,6 +592,8 @@ int GrammarCompare::compare(const grammar::RightLG& a, const grammar::RightLG& b
 	}
 }
 
+auto GrammarCompareRightLG = GrammarCompare::RegistratorWrapper<int, grammar::RightLG, grammar::RightLG>(GrammarCompare::getInstance(), GrammarCompare::compare);
+
 int GrammarCompare::compare(const grammar::RightRG& a, const grammar::RightRG& b) {
 	if(!GrammarCompare::testCompare(a, b)) {
 	  GrammarCompare::printCompare(a, b);
@@ -597,6 +603,8 @@ int GrammarCompare::compare(const grammar::RightRG& a, const grammar::RightRG& b
 	}
 }
 
+auto GrammarCompareRightRG = GrammarCompare::RegistratorWrapper<int, grammar::RightRG, grammar::RightRG>(GrammarCompare::getInstance(), GrammarCompare::compare);
+
 int GrammarCompare::compare(const grammar::LG& a, const grammar::LG& b) {
 	if(!GrammarCompare::testCompare(a, b)) {
 	  GrammarCompare::printCompare(a, b);
@@ -606,6 +614,8 @@ int GrammarCompare::compare(const grammar::LG& a, const grammar::LG& b) {
 	}
 }
 
+auto GrammarCompareLG = GrammarCompare::RegistratorWrapper<int, grammar::LG, grammar::LG>(GrammarCompare::getInstance(), GrammarCompare::compare);
+
 int GrammarCompare::compare(const grammar::CFG& a, const grammar::CFG& b) {
 	if(!GrammarCompare::testCompare(a, b)) {
 	  GrammarCompare::printCompare(a, b);
@@ -615,6 +625,8 @@ int GrammarCompare::compare(const grammar::CFG& a, const grammar::CFG& b) {
 	}
 }
 
+auto GrammarCompareCFG = GrammarCompare::RegistratorWrapper<int, grammar::CFG, grammar::CFG>(GrammarCompare::getInstance(), GrammarCompare::compare);
+
 int GrammarCompare::compare(const grammar::EpsilonFreeCFG& a, const grammar::EpsilonFreeCFG& b) {
 	if(!GrammarCompare::testCompare(a, b)) {
 	  GrammarCompare::printCompare(a, b);
@@ -624,6 +636,8 @@ int GrammarCompare::compare(const grammar::EpsilonFreeCFG& a, const grammar::Eps
 	}
 }
 
+auto GrammarCompareEpsilonFreeCFG = GrammarCompare::RegistratorWrapper<int, grammar::EpsilonFreeCFG, grammar::EpsilonFreeCFG>(GrammarCompare::getInstance(), GrammarCompare::compare);
+
 int GrammarCompare::compare(const grammar::CNF& a, const grammar::CNF& b) {
 	if(!GrammarCompare::testCompare(a, b)) {
 	  GrammarCompare::printCompare(a, b);
@@ -633,6 +647,8 @@ int GrammarCompare::compare(const grammar::CNF& a, const grammar::CNF& b) {
 	}
 }
 
+auto GrammarCompareCNF = GrammarCompare::RegistratorWrapper<int, grammar::CNF, grammar::CNF>(GrammarCompare::getInstance(), GrammarCompare::compare);
+
 int GrammarCompare::compare(const grammar::GNF& a, const grammar::GNF& b) {
 	if(!GrammarCompare::testCompare(a, b)) {
 	  GrammarCompare::printCompare(a, b);
@@ -642,6 +658,8 @@ int GrammarCompare::compare(const grammar::GNF& a, const grammar::GNF& b) {
 	}
 }
 
+auto GrammarCompareGNF = GrammarCompare::RegistratorWrapper<int, grammar::GNF, grammar::GNF>(GrammarCompare::getInstance(), GrammarCompare::compare);
+
 int GrammarCompare::compare(const grammar::CSG& a, const grammar::CSG& b) {
 	if(!GrammarCompare::testCompare(a, b)) {
 	  GrammarCompare::printCompare(a, b);
@@ -651,6 +669,8 @@ int GrammarCompare::compare(const grammar::CSG& a, const grammar::CSG& b) {
 	}
 }
 
+auto GrammarCompareCSG = GrammarCompare::RegistratorWrapper<int, grammar::CSG, grammar::CSG>(GrammarCompare::getInstance(), GrammarCompare::compare);
+
 int GrammarCompare::compare(const grammar::NonContractingGrammar& a, const grammar::NonContractingGrammar& b) {
 	if(!GrammarCompare::testCompare(a, b)) {
 	  GrammarCompare::printCompare(a, b);
@@ -660,6 +680,8 @@ int GrammarCompare::compare(const grammar::NonContractingGrammar& a, const gramm
 	}
 }
 
+auto GrammarCompareNonContractingGrammar = GrammarCompare::RegistratorWrapper<int, grammar::NonContractingGrammar, grammar::NonContractingGrammar>(GrammarCompare::getInstance(), GrammarCompare::compare);
+
 int GrammarCompare::compare(const grammar::ContextPreservingUnrestrictedGrammar& a, const grammar::ContextPreservingUnrestrictedGrammar& b) {
 	if(!GrammarCompare::testCompare(a, b)) {
 	  GrammarCompare::printCompare(a, b);
@@ -669,6 +691,8 @@ int GrammarCompare::compare(const grammar::ContextPreservingUnrestrictedGrammar&
 	}
 }
 
+auto GrammarCompareContextPreservingUnrestrictedGrammar = GrammarCompare::RegistratorWrapper<int, grammar::ContextPreservingUnrestrictedGrammar, grammar::ContextPreservingUnrestrictedGrammar>(GrammarCompare::getInstance(), GrammarCompare::compare);
+
 int GrammarCompare::compare(const grammar::UnrestrictedGrammar& a, const grammar::UnrestrictedGrammar& b) {
 	if(!GrammarCompare::testCompare(a, b)) {
 	  GrammarCompare::printCompare(a, b);
@@ -678,63 +702,9 @@ int GrammarCompare::compare(const grammar::UnrestrictedGrammar& a, const grammar
 	}
 }
 
-int GrammarCompare::compare(const grammar::Grammar& a, const grammar::Grammar& b) {
-	int res;
-	Accept((void*) &res, a.getData(), b.getData(), GrammarCompare::GRAMMAR_COMPARE);
-	return res;
-}
-
-void GrammarCompare::Visit(void* data, const grammar::RightRG& first, const grammar::RightRG& second) const {
-	*((int*) data) = GrammarCompare::compare(first, second);
-}
-
-void GrammarCompare::Visit(void* data, const grammar::LeftRG& first, const grammar::LeftRG& second) const {
-	*((int*) data) = GrammarCompare::compare(first, second);
-}
-
-void GrammarCompare::Visit(void* data, const grammar::RightLG& first, const grammar::RightLG& second) const {
-	*((int*) data) = GrammarCompare::compare(first, second);
-}
-
-void GrammarCompare::Visit(void* data, const grammar::LeftLG& first, const grammar::LeftLG& second) const {
-	*((int*) data) = GrammarCompare::compare(first, second);
-}
-
-void GrammarCompare::Visit(void* data, const grammar::LG& first, const grammar::LG& second) const {
-	*((int*) data) = GrammarCompare::compare(first, second);
-}
-
-void GrammarCompare::Visit(void* data, const grammar::CFG& first, const grammar::CFG& second) const {
-	*((int*) data) = GrammarCompare::compare(first, second);
-}
-
-void GrammarCompare::Visit(void* data, const grammar::EpsilonFreeCFG& first, const grammar::EpsilonFreeCFG& second) const {
-	*((int*) data) = GrammarCompare::compare(first, second);
-}
-
-void GrammarCompare::Visit(void* data, const grammar::CNF& first, const grammar::CNF& second) const {
-	*((int*) data) = GrammarCompare::compare(first, second);
-}
-
-void GrammarCompare::Visit(void* data, const grammar::GNF& first, const grammar::GNF& second) const {
-	*((int*) data) = GrammarCompare::compare(first, second);
-}
-
-void GrammarCompare::Visit(void* data, const grammar::CSG& first, const grammar::CSG& second) const {
-	*((int*) data) = GrammarCompare::compare(first, second);
-}
-
-void GrammarCompare::Visit(void* data, const grammar::NonContractingGrammar& first, const grammar::NonContractingGrammar& second) const {
-	*((int*) data) = GrammarCompare::compare(first, second);
-}
-
-void GrammarCompare::Visit(void* data, const grammar::ContextPreservingUnrestrictedGrammar& first, const grammar::ContextPreservingUnrestrictedGrammar& second) const {
-	*((int*) data) = GrammarCompare::compare(first, second);
-}
+auto GrammarCompareUnrestrictedGrammar = GrammarCompare::RegistratorWrapper<int, grammar::UnrestrictedGrammar, grammar::UnrestrictedGrammar>(GrammarCompare::getInstance(), GrammarCompare::compare);
 
-void GrammarCompare::Visit(void* data, const grammar::UnrestrictedGrammar& first, const grammar::UnrestrictedGrammar& second) const {
-	*((int*) data) = GrammarCompare::compare(first, second);
+int GrammarCompare::compare(const grammar::Grammar& a, const grammar::Grammar& b) {
+	return getInstance().dispatch(a.getData(), b.getData());
 }
 
-const GrammarCompare GrammarCompare::GRAMMAR_COMPARE;
-
diff --git a/acompare2/src/GrammarCompare.h b/acompare2/src/GrammarCompare.h
index c39fdc165710a2423a2deefaa0983db17468b73f..26d523521a1a826c90ce66cdf2a6c75be474d13d 100644
--- a/acompare2/src/GrammarCompare.h
+++ b/acompare2/src/GrammarCompare.h
@@ -8,18 +8,17 @@
 #ifndef GRAMMAR_COMPARE_H_
 #define GRAMMAR_COMPARE_H_
 
+#include <common/multipleDispatch.hpp>
 #include <ostream>
 
 #include <grammar/Grammar.h>
+#include <grammar/GrammarFeatures.h>
 #include <set>
 #include <list>
 #include <map>
 #include <utility>
 
-class GrammarCompare : public grammar::VisitableGrammarBase::const_same_visitor_type {
-public:
-	GrammarCompare() {}
-
+class GrammarCompare : public std::DoubleDispatch<int, grammar::GrammarBase, grammar::GrammarBase> {
 private:
 	static bool testCompare(const grammar::LeftLG& a, const grammar::LeftLG& b);
 	static void printCompare(const grammar::LeftLG& a, const grammar::LeftLG& b);
@@ -64,23 +63,6 @@ private:
 	template <class T> static void listCompare(const std::list<T> a, const std::list<T> b);
 	template <class T, class R> static void mapCompare(const std::map<T, R> a, const std::map<T, R> b);
 public:
-	void Visit(void*, const grammar::RightRG& first, const grammar::RightRG& second) const;
-	void Visit(void*, const grammar::LeftRG& first, const grammar::LeftRG& second) const;
-	void Visit(void*, const grammar::RightLG& first, const grammar::RightLG& second) const;
-	void Visit(void*, const grammar::LeftLG& first, const grammar::LeftLG& second) const;
-
-	void Visit(void*, const grammar::LG& first, const grammar::LG& second) const;
-	void Visit(void*, const grammar::CFG& first, const grammar::CFG& second) const;
-	void Visit(void*, const grammar::EpsilonFreeCFG& first, const grammar::EpsilonFreeCFG& second) const;
-	void Visit(void*, const grammar::CNF& first, const grammar::CNF& second) const;
-	void Visit(void*, const grammar::GNF& first, const grammar::GNF& second) const;
-
-	void Visit(void*, const grammar::CSG& first, const grammar::CSG& second) const;
-	void Visit(void*, const grammar::NonContractingGrammar& first, const grammar::NonContractingGrammar& second) const;
-
-	void Visit(void*, const grammar::ContextPreservingUnrestrictedGrammar& first, const grammar::ContextPreservingUnrestrictedGrammar& second) const;
-	void Visit(void*, const grammar::UnrestrictedGrammar& first, const grammar::UnrestrictedGrammar& second) const;
-
 	static int compare(const grammar::LeftLG& a, const grammar::LeftLG& b);
 	static int compare(const grammar::LeftRG& a, const grammar::LeftRG& b);
 	static int compare(const grammar::RightLG& a, const grammar::RightLG& b);
@@ -97,7 +79,10 @@ public:
 
 	static int compare(const grammar::Grammar& a, const grammar::Grammar& b);
 
-	static const GrammarCompare GRAMMAR_COMPARE;
+	static GrammarCompare& getInstance() {
+		static GrammarCompare res;
+		return res;
+	}
 };
 
 #endif /* GRAMMAR_COMPARE_H_ */
diff --git a/aconvert2/src/DotConverter.h b/aconvert2/src/DotConverter.h
index b9d4ed32b2ff08dec289d52e124b67ec3fb81378..735fcc6bbd43f218569902788db3b83962365d49 100644
--- a/aconvert2/src/DotConverter.h
+++ b/aconvert2/src/DotConverter.h
@@ -17,7 +17,7 @@
 #include <map>
 #include <utility>
 
-class DotConverter : public std::SingleDispatchFirstStaticParam<void, std::ostream, automaton::AutomatonBase> {
+class DotConverter : public std::SingleDispatchFirstStaticParam<void, std::ostream&, automaton::AutomatonBase> {
 	static void transitions(const automaton::EpsilonNFA& fsm, const std::map<automaton::State, int>& states, std::ostream& out);
 	static void transitions(const automaton::MultiInitialStateNFA& fsm, const std::map<automaton::State, int>& states, std::ostream& out);
 	static void transitions(const automaton::NFA& fsm, const std::map<automaton::State, int>& states, std::ostream& out);
diff --git a/aconvert2/src/GasTexConverter.h b/aconvert2/src/GasTexConverter.h
index 9de2682c033996f1ffa9d4d26b58d4c886f9ce72..92962ccf5c43c8f7cd8d94985e924c9772c9b10e 100644
--- a/aconvert2/src/GasTexConverter.h
+++ b/aconvert2/src/GasTexConverter.h
@@ -16,7 +16,7 @@
 #include "automaton/Automaton.h"
 #include "alphabet/Symbol.h"
 
-class GasTexConverter : public std::SingleDispatchFirstStaticParam<void, std::ostream, automaton::AutomatonBase> {
+class GasTexConverter : public std::SingleDispatchFirstStaticParam<void, std::ostream&, automaton::AutomatonBase> {
 	static void printTransitionMap( const std::map<std::pair<std::string, std::string>, std::string> transitionMap, std::ostream& out);
 	static std::string getStackSymbols(const std::vector<alphabet::Symbol>& stackSymbols);
 
diff --git a/alib2algo/src/arbology/exact/ExactSubtreeMatch.h b/alib2algo/src/arbology/exact/ExactSubtreeMatch.h
index c596fd04190fa0ecd0c1623ad056696b03ba917c..e87037a7acee1a1d65680510a1ecea350fab0822 100644
--- a/alib2algo/src/arbology/exact/ExactSubtreeMatch.h
+++ b/alib2algo/src/arbology/exact/ExactSubtreeMatch.h
@@ -9,6 +9,7 @@
 #define _EXACT_SUBTREE_MATCH_H_
 
 #include <tree/Tree.h>
+#include <tree/TreeFeatures.h>
 #include <tree/ranked/RankedNode.h>
 #include <tree/unranked/UnrankedNode.h>
 #include <set>
diff --git a/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.h b/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.h
index 436eb92390e755bf457aa5ec66efa5f9a9598a40..715e1f3cfb7da88111382292e68cbca9ea10e09b 100644
--- a/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.h
+++ b/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.h
@@ -12,6 +12,7 @@
 #include <automaton/PDA/InputDrivenNPDA.h>
 #include <automaton/TA/NFTA.h>
 #include <tree/Tree.h>
+#include <tree/TreeFeatures.h>
 #include <common/multipleDispatch.hpp>
 
 namespace arbology {
diff --git a/alib2algo/src/automaton/properties/EpsilonClosure.h b/alib2algo/src/automaton/properties/EpsilonClosure.h
index 4b156c6e9314ac6c0634325246215ccc53ff47ba..df15acee6db9bc8f5bed73e44b895cbaf09379ba 100644
--- a/alib2algo/src/automaton/properties/EpsilonClosure.h
+++ b/alib2algo/src/automaton/properties/EpsilonClosure.h
@@ -20,7 +20,7 @@ namespace automaton {
 
 namespace properties {
 
-class EpsilonClosure : public std::SingleDispatchLastStaticParam<std::set<automaton::State>, automaton::AutomatonBase, const automaton::State> {
+class EpsilonClosure : public std::SingleDispatchLastStaticParam<std::set<automaton::State>, automaton::AutomatonBase, const automaton::State&> {
 public:
 	static std::set<automaton::State> epsilonClosure( const automaton::Automaton & automaton, const automaton::State & state );
 
diff --git a/alib2algo/src/grammar/generate/GenerateUpToLength.cpp b/alib2algo/src/grammar/generate/GenerateUpToLength.cpp
index 33d7d6bdac8ce48c5f82728fe621466abd7713a1..221495bb93b428445aab114ce0cc6164c5c85c27 100644
--- a/alib2algo/src/grammar/generate/GenerateUpToLength.cpp
+++ b/alib2algo/src/grammar/generate/GenerateUpToLength.cpp
@@ -61,78 +61,16 @@ std::set<string::LinearString> GenerateUpToLength::generate( const T & grammar,
 	return res;
 }
 
-template std::set<string::LinearString> GenerateUpToLength::generate( const grammar::EpsilonFreeCFG & grammar, unsigned length );
-template std::set<string::LinearString> GenerateUpToLength::generate( const grammar::GNF & grammar, unsigned length );
-template std::set<string::LinearString> GenerateUpToLength::generate( const grammar::CNF & grammar, unsigned length );
-template std::set<string::LinearString> GenerateUpToLength::generate( const grammar::LeftRG & grammar, unsigned length );
-template std::set<string::LinearString> GenerateUpToLength::generate( const grammar::RightRG & grammar, unsigned length );
+auto GenerateUpToLengthEpsilonFreeCFG = GenerateUpToLength::RegistratorWrapper<std::set<string::LinearString>, grammar::EpsilonFreeCFG>(GenerateUpToLength::getInstance(), GenerateUpToLength::generate);
+auto GenerateUpToLengthGNF = GenerateUpToLength::RegistratorWrapper<std::set<string::LinearString>, grammar::GNF>(GenerateUpToLength::getInstance(), GenerateUpToLength::generate);
+auto GenerateUpToLengthCNF = GenerateUpToLength::RegistratorWrapper<std::set<string::LinearString>, grammar::CNF>(GenerateUpToLength::getInstance(), GenerateUpToLength::generate);
+auto GenerateUpToLengthLeftRG = GenerateUpToLength::RegistratorWrapper<std::set<string::LinearString>, grammar::LeftRG>(GenerateUpToLength::getInstance(), GenerateUpToLength::generate);
+auto GenerateUpToLengthRightRG = GenerateUpToLength::RegistratorWrapper<std::set<string::LinearString>, grammar::RightRG>(GenerateUpToLength::getInstance(), GenerateUpToLength::generate);
 
 std::set<string::LinearString> GenerateUpToLength::generate(const grammar::Grammar& grammar, unsigned length) {
-	std::pair<std::set<string::LinearString>, unsigned> out;
-	out.second = length;
-	grammar.getData().Accept((void*) &out, GenerateUpToLength::GENERATE_UP_TO_LENGTH);
-	return std::move(out.first);
+	return getInstance().dispatch(grammar.getData(), length);
 }
 
-void GenerateUpToLength::Visit(void*, const grammar::LeftLG&) const {
-	throw exception::AlibException("Unsupported grammar type LeftLG");
-}
-
-void GenerateUpToLength::Visit(void* data, const grammar::LeftRG& grammar) const {
-	std::pair<std::set<string::LinearString>, unsigned>& out = *((std::pair<std::set<string::LinearString>, unsigned>*) data);
-	out.first = this->generate(grammar, out.second);
-}
-
-void GenerateUpToLength::Visit(void*, const grammar::RightLG&) const {
-	throw exception::AlibException("Unsupported grammar type RightLG");
-}
-
-void GenerateUpToLength::Visit(void* data, const grammar::RightRG& grammar) const {
-	std::pair<std::set<string::LinearString>, unsigned>& out = *((std::pair<std::set<string::LinearString>, unsigned>*) data);
-	out.first = this->generate(grammar, out.second);
-}
-
-void GenerateUpToLength::Visit(void*, const grammar::LG&) const {
-	throw exception::AlibException("Unsupported grammar type LG");
-}
-
-void GenerateUpToLength::Visit(void*, const grammar::CFG&) const {
-	throw exception::AlibException("Unsupported grammar type CFG");
-}
-
-void GenerateUpToLength::Visit(void* data, const grammar::EpsilonFreeCFG& grammar) const {
-	std::pair<std::set<string::LinearString>, unsigned>& out = *((std::pair<std::set<string::LinearString>, unsigned>*) data);
-	out.first = this->generate(grammar, out.second);
-}
-
-void GenerateUpToLength::Visit(void* data, const grammar::CNF& grammar) const {
-	std::pair<std::set<string::LinearString>, unsigned>& out = *((std::pair<std::set<string::LinearString>, unsigned>*) data);
-	out.first = this->generate(grammar, out.second);
-}
-
-void GenerateUpToLength::Visit(void* data, const grammar::GNF& grammar) const {
-	std::pair<std::set<string::LinearString>, unsigned>& out = *((std::pair<std::set<string::LinearString>, unsigned>*) data);
-	out.first = this->generate(grammar, out.second);
-}
-
-void GenerateUpToLength::Visit(void*, const grammar::CSG&) const {
-	throw exception::AlibException("Unsupported grammar type CSG");
-}
-
-void GenerateUpToLength::Visit(void*, const grammar::NonContractingGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type NonConctractingGrammar");
-}
-
-void GenerateUpToLength::Visit(void*, const grammar::ContextPreservingUnrestrictedGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type ContextPreservingUnrestrictedGrammar");
-}
-
-void GenerateUpToLength::Visit(void*, const grammar::UnrestrictedGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type UnrestrictedGrammar");
-}
-
-const GenerateUpToLength GenerateUpToLength::GENERATE_UP_TO_LENGTH;
-
 } /* namespace generate */
 
 } /* namespace grammar */
diff --git a/alib2algo/src/grammar/generate/GenerateUpToLength.h b/alib2algo/src/grammar/generate/GenerateUpToLength.h
index 26b2d1fc8bd1b0febf4efc8dc5186659ea35cb04..0a1abcf8d5c5f456eff3c9d5fdcff2be2925c215 100644
--- a/alib2algo/src/grammar/generate/GenerateUpToLength.h
+++ b/alib2algo/src/grammar/generate/GenerateUpToLength.h
@@ -8,6 +8,8 @@
 #ifndef GRAMMAR_GENERATE_UP_TO_LENGTH_H_
 #define GRAMMAR_GENERATE_UP_TO_LENGTH_H_
 
+#include <common/multipleDispatch.hpp>
+
 #include <grammar/Grammar.h>
 #include <string/LinearString.h>
 #include <set>
@@ -19,31 +21,17 @@ namespace generate {
 /**
  * Implements algorithms from Melichar, chapter 3.3
  */
-class GenerateUpToLength : public grammar::VisitableGrammarBase::const_visitor_type {
+class GenerateUpToLength : public std::SingleDispatchLastStaticParam<std::set<string::LinearString>, grammar::GrammarBase, unsigned> {
 public:
-	GenerateUpToLength() {}
-
 	static std::set<string::LinearString> generate( const grammar::Grammar & grammar, unsigned length );
 
 	template<class T>
 	static std::set<string::LinearString> generate( const T & grammar, unsigned length );
 
-private:
-	void Visit(void*, const grammar::LeftLG& grammar) const;
-	void Visit(void*, const grammar::LeftRG& grammar) const;
-	void Visit(void*, const grammar::RightLG& grammar) const;
-	void Visit(void*, const grammar::RightRG& grammar) const;
-	void Visit(void*, const grammar::LG& grammar) const;
-	void Visit(void*, const grammar::CFG& grammar) const;
-	void Visit(void*, const grammar::EpsilonFreeCFG& grammar) const;
-	void Visit(void*, const grammar::CNF& grammar) const;
-	void Visit(void*, const grammar::GNF& grammar) const;
-	void Visit(void*, const grammar::CSG& grammar) const;
-	void Visit(void*, const grammar::NonContractingGrammar& grammar) const;
-	void Visit(void*, const grammar::ContextPreservingUnrestrictedGrammar& grammar) const;
-	void Visit(void*, const grammar::UnrestrictedGrammar& grammar) const;
-
-	static const GenerateUpToLength GENERATE_UP_TO_LENGTH;
+	static GenerateUpToLength& getInstance() {
+		static GenerateUpToLength res;
+		return res;
+	}
 };
 
 } /* namespace generate */
diff --git a/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.h b/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.h
index 62c9206b9467a92b3eef83a6b09a9a527c664886..9cb25fe022831dac472e3e109f4b7736d6d1066f 100644
--- a/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.h
+++ b/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.h
@@ -20,7 +20,7 @@ namespace properties {
 /**
  * Implements algorithms from Melichar, chapter 3.3
  */
-class NonterminalUnitRuleCycle : public std::SingleDispatchLastStaticParam<std::set<alphabet::Symbol>, grammar::GrammarBase, const alphabet::Symbol> {
+class NonterminalUnitRuleCycle : public std::SingleDispatchLastStaticParam<std::set<alphabet::Symbol>, grammar::GrammarBase, const alphabet::Symbol&> {
 public:
 	static std::set<alphabet::Symbol> getNonterminalUnitRuleCycle( const grammar::Grammar & grammar, const alphabet::Symbol& nonterminal );
 
diff --git a/alib2algo/src/grammar/simplify/ToGNF.h b/alib2algo/src/grammar/simplify/ToGNF.h
index 4f9662646b9a744c7ef3444756586928a99a5168..bc7ece377751d41b9e56f9ddd5c03397834673b7 100644
--- a/alib2algo/src/grammar/simplify/ToGNF.h
+++ b/alib2algo/src/grammar/simplify/ToGNF.h
@@ -16,7 +16,7 @@
 
 #include <grammar/ContextFree/CFG.h>
 #include <grammar/ContextFree/EpsilonFreeCFG.h>
-#include <grammar/ContextFree/GNF.h>
+#include <grammar/ContextFree/CNF.h>
 #include <grammar/ContextFree/GNF.h>
 #include <grammar/ContextFree/LG.h>
 #include <grammar/Regular/LeftLG.h>
diff --git a/alib2algo/src/graph/shortestpath/BellmanFord.h b/alib2algo/src/graph/shortestpath/BellmanFord.h
index 9c5a07e2dd8d6a889b8b9f1e1cc0fef6b045b6b2..f6ae2e77ae053bf322455fcdeb77ae0eba94130a 100644
--- a/alib2algo/src/graph/shortestpath/BellmanFord.h
+++ b/alib2algo/src/graph/shortestpath/BellmanFord.h
@@ -17,7 +17,7 @@ namespace shortestpath {
 //
 // note: negative-weight undirected edge = negative-weight cycle
 
-class BellmanFord : public std::SingleDispatchLastStaticParam<std::unordered_map<Node, int>, graph::GraphBase, const Node> {
+class BellmanFord : public std::SingleDispatchLastStaticParam<std::unordered_map<Node, int>, graph::GraphBase, const Node&> {
 public:
 	typedef std::unordered_map<Node, int> Result;
 
diff --git a/alib2algo/src/graph/shortestpath/Dijkstra.h b/alib2algo/src/graph/shortestpath/Dijkstra.h
index d1fc6af8c6ce9f6fe904141bf02e7c2b94bc4beb..46bfa79a5387fe86c1f1d60c937c6c8d613693ec 100644
--- a/alib2algo/src/graph/shortestpath/Dijkstra.h
+++ b/alib2algo/src/graph/shortestpath/Dijkstra.h
@@ -14,7 +14,7 @@ namespace shortestpath {
 
 // Dijkstra only works on graphs without negative-weight edges (>= 0)
 
-class Dijkstra : public std::SingleDispatchLastStaticParam<std::unordered_map<Node, int>, graph::GraphBase, const Node> {
+class Dijkstra : public std::SingleDispatchLastStaticParam<std::unordered_map<Node, int>, graph::GraphBase, const Node&> {
 public:
 	typedef std::unordered_map<Node, int> Result;
 
diff --git a/alib2algo/src/graph/spanningtree/JarnikPrim.h b/alib2algo/src/graph/spanningtree/JarnikPrim.h
index 05d80541248961547d7e8e6daab7bc938c849687..8489805fd2b228e0f8e51a2ab546c4e83c4375c6 100644
--- a/alib2algo/src/graph/spanningtree/JarnikPrim.h
+++ b/alib2algo/src/graph/spanningtree/JarnikPrim.h
@@ -10,7 +10,7 @@ namespace graph {
 
 namespace spanningtree {
 
-class JarnikPrim : public std::SingleDispatchLastStaticParam<graph::Graph, graph::GraphBase, const Node> {
+class JarnikPrim : public std::SingleDispatchLastStaticParam<graph::Graph, graph::GraphBase, const Node&> {
 public:
 	static Graph jarnikprim(const Graph &graph, const Node &start);
 
diff --git a/alib2algo/src/regexp/convert/ToGrammar.h b/alib2algo/src/regexp/convert/ToGrammar.h
index 6adfdcd34376842a67b1b1caa1b7feccda49bb08..7af33ebe963a00922d2a9b77a73d1345fbca0800 100644
--- a/alib2algo/src/regexp/convert/ToGrammar.h
+++ b/alib2algo/src/regexp/convert/ToGrammar.h
@@ -12,6 +12,7 @@
 
 #include <grammar/Grammar.h>
 #include <regexp/RegExp.h>
+#include <regexp/RegExpFeatures.h>
 
 namespace regexp {
 
diff --git a/alib2algo/src/regexp/transform/RegExpDerivation.h b/alib2algo/src/regexp/transform/RegExpDerivation.h
index 5f0907b192fb6739f0381b626b9eb3241a0070b3..71ea567a20e857724d808785a27a5d712997f3e9 100644
--- a/alib2algo/src/regexp/transform/RegExpDerivation.h
+++ b/alib2algo/src/regexp/transform/RegExpDerivation.h
@@ -25,7 +25,7 @@ namespace regexp {
  *  - Melichar, definition 2.91 in chapter 2.4.3
  *  - Brzozowski, J. A. - Derivatives of regular expressions (1964)
  */
-class RegExpDerivation : public std::SingleDispatchLastStaticParam<regexp::RegExp, regexp::RegExpBase, const string::LinearString>, regexp::FormalRegExpElement::const_visitor_type, regexp::UnboundedRegExpElement::const_visitor_type {
+class RegExpDerivation : public std::SingleDispatchLastStaticParam<regexp::RegExp, regexp::RegExpBase, const string::LinearString&>, regexp::FormalRegExpElement::const_visitor_type, regexp::UnboundedRegExpElement::const_visitor_type {
 public:
 	RegExpDerivation() {}
 
diff --git a/alib2algo/src/regexp/transform/RegExpIntegral.h b/alib2algo/src/regexp/transform/RegExpIntegral.h
index defdf94aea70b69d7f756e069e1bd89dbaa155d5..6457207a9d84be19aa22c1bbeee2c919f92223ab 100644
--- a/alib2algo/src/regexp/transform/RegExpIntegral.h
+++ b/alib2algo/src/regexp/transform/RegExpIntegral.h
@@ -23,7 +23,7 @@ namespace regexp
  * Calculates integral of regular expression
  * Source: Melichar definition 2.93 in chapter 2.4.4
  */
-class RegExpIntegral : public std::SingleDispatchLastStaticParam<regexp::RegExp, regexp::RegExpBase, const string::LinearString>, regexp::FormalRegExpElement::const_visitor_type, regexp::UnboundedRegExpElement::const_visitor_type
+class RegExpIntegral : public std::SingleDispatchLastStaticParam<regexp::RegExp, regexp::RegExpBase, const string::LinearString&>, regexp::FormalRegExpElement::const_visitor_type, regexp::UnboundedRegExpElement::const_visitor_type
 {
 public:
 	RegExpIntegral() {}
diff --git a/alib2algo/src/string/naive/ExactCompare.h b/alib2algo/src/string/naive/ExactCompare.h
index fc4825128a9fb5940a91a700d25505f25b218afc..e6597d8cb1657468b08c9a7b7025cbf6891c4798 100644
--- a/alib2algo/src/string/naive/ExactCompare.h
+++ b/alib2algo/src/string/naive/ExactCompare.h
@@ -10,6 +10,7 @@
 
 #include <common/multipleDispatch.hpp>
 #include <string/String.h>
+#include <string/StringFeatures.h>
 
 namespace string {
 
diff --git a/alib2algo/src/string/naive/ExactEqual.h b/alib2algo/src/string/naive/ExactEqual.h
index 991b94dbcf079c653d13c1018b4fc75309e150b2..88826e59d9b35243a6a57682eff8cf40ee381bde 100644
--- a/alib2algo/src/string/naive/ExactEqual.h
+++ b/alib2algo/src/string/naive/ExactEqual.h
@@ -10,6 +10,7 @@
 
 #include <common/multipleDispatch.hpp>
 #include <string/String.h>
+#include <string/StringFeatures.h>
 
 namespace string {
 
diff --git a/alib2algo/src/string/simplify/NormalizeRotation.h b/alib2algo/src/string/simplify/NormalizeRotation.h
index b8c1817fb67185e4253966ea59444017843857d2..aaa69df69da5bdf37fb6168baee71a1856fb2d3d 100644
--- a/alib2algo/src/string/simplify/NormalizeRotation.h
+++ b/alib2algo/src/string/simplify/NormalizeRotation.h
@@ -11,6 +11,7 @@
 #include <common/multipleDispatch.hpp>
 
 #include <string/String.h>
+#include <string/StringFeatures.h>
 
 namespace string {
 
diff --git a/alib2algo/src/stringology/exact/BadCharacterShiftTable.h b/alib2algo/src/stringology/exact/BadCharacterShiftTable.h
index 0fcae07f1e8697ed4f1c04b2a72745a355c81574..b8839b7de84bdaefe5b2293993ddf153ce246541 100644
--- a/alib2algo/src/stringology/exact/BadCharacterShiftTable.h
+++ b/alib2algo/src/stringology/exact/BadCharacterShiftTable.h
@@ -23,7 +23,7 @@ namespace exact {
  * Computation of BCS table for BMH from MI(E+\eps)-EVY course 2014
  * To get rid of zeros in BCS table we ignore last haystack character
  */
-class BadCharacterShiftTable : public std::SingleDispatchFirstStaticParam<std::map<alphabet::Symbol, size_t>, const std::set<alphabet::Symbol>, string::StringBase> {
+class BadCharacterShiftTable : public std::SingleDispatchFirstStaticParam<std::map<alphabet::Symbol, size_t>, const std::set<alphabet::Symbol>&, string::StringBase> {
 public:
 	/**
 	 * Search for pattern in linear string.
diff --git a/alib2data/src/common/multipleDispatch.hpp b/alib2data/src/common/multipleDispatch.hpp
index 84a00a59782b7e5adf4b8139dcfad16a1ae31e13..5b34f5b554b0a46dd65818dfb5f736da875d75da 100644
--- a/alib2data/src/common/multipleDispatch.hpp
+++ b/alib2data/src/common/multipleDispatch.hpp
@@ -61,7 +61,7 @@ class SingleDispatchFirstStaticParam {
 public:
 	class RegistratorWrapperBase {
 	public:
-		virtual ReturnType eval(StaticParamType&, const FirstParameterType&) = 0;
+		virtual ReturnType eval(StaticParamType, const FirstParameterType&) = 0;
 
 	};
 
@@ -73,21 +73,21 @@ private:
 public:
 	template<class RealReturnType, class RealFirstParameterType>
 	class RegistratorWrapper : public RegistratorWrapperBase {
-		std::function<RealReturnType(StaticParamType&, const RealFirstParameterType&)> callback;
+		std::function<RealReturnType(StaticParamType, const RealFirstParameterType&)> callback;
 
 	public:
-		ReturnType eval(StaticParamType& res, const FirstParameterType& first) {
+		ReturnType eval(StaticParamType res, const FirstParameterType& first) {
 			return ReturnType(callback(res, (const RealFirstParameterType&) first));
 		}
 
-		RegistratorWrapper(SelfType& pool, RealReturnType(*callback)(StaticParamType&, const RealFirstParameterType&)) : callback(callback) {
+		RegistratorWrapper(SelfType& pool, RealReturnType(*callback)(StaticParamType, const RealFirstParameterType&)) : callback(callback) {
 			int a = 0;
 			if(! pool.registeredFunctions.insert(std::make_pair(RealFirstParameterType::typeId((const RealFirstParameterType&) a), this)).second )
 				throw std::logic_error("Callback alreary registered.");
 		}
 	};
 
-	ReturnType dispatch(StaticParamType& res, const FirstParameterType& first) {
+	ReturnType dispatch(StaticParamType res, const FirstParameterType& first) {
 		typename std::map<long long, RegistratorWrapperBase*>::iterator callback = registeredFunctions.find(first.selfTypeId());
 		if(callback == registeredFunctions.end()) throw std::bad_function_call();
 		return callback->second->eval(res, first);
@@ -100,7 +100,7 @@ class SingleDispatchLastStaticParam {
 public:
 	class RegistratorWrapperBase {
 	public:
-		virtual ReturnType eval(const FirstParameterType&, StaticParamType&) = 0;
+		virtual ReturnType eval(const FirstParameterType&, StaticParamType) = 0;
 
 	};
 
@@ -112,21 +112,21 @@ private:
 public:
 	template<class RealReturnType, class RealFirstParameterType>
 	class RegistratorWrapper : public RegistratorWrapperBase {
-		std::function<RealReturnType(const RealFirstParameterType&, StaticParamType&)> callback;
+		std::function<RealReturnType(const RealFirstParameterType&, StaticParamType)> callback;
 
 	public:
-		ReturnType eval(const FirstParameterType& first, StaticParamType& res) {
+		ReturnType eval(const FirstParameterType& first, StaticParamType res) {
 			return ReturnType(callback((const RealFirstParameterType&) first, res));
 		}
 
-		RegistratorWrapper(SelfType& pool, RealReturnType(*callback)(const RealFirstParameterType&, StaticParamType&)) : callback(callback) {
+		RegistratorWrapper(SelfType& pool, RealReturnType(*callback)(const RealFirstParameterType&, StaticParamType)) : callback(callback) {
 			int a = 0;
 			if(! pool.registeredFunctions.insert(std::make_pair(RealFirstParameterType::typeId((const RealFirstParameterType&) a), this)). second)
 				throw std::logic_error("Callback alreary registered.");
 		}
 	};
 
-	ReturnType dispatch(const FirstParameterType& first, StaticParamType& res) {
+	ReturnType dispatch(const FirstParameterType& first, StaticParamType res) {
 		typename std::map<long long, RegistratorWrapperBase*>::iterator callback = registeredFunctions.find(first.selfTypeId());
 		if(callback == registeredFunctions.end()) throw std::bad_function_call();
 		return callback->second->eval(first, res);
@@ -282,7 +282,7 @@ class DoubleDispatchFirstStaticParam {
 public:
 	class RegistratorWrapperBase {
 	public:
-		virtual ReturnType eval(StaticParamType&, const FirstParameterType&, const SecondParameterType&) = 0;
+		virtual ReturnType eval(StaticParamType, const FirstParameterType&, const SecondParameterType&) = 0;
 
 	};
 
@@ -294,21 +294,21 @@ private:
 public:
 	template<class RealReturnType, class RealFirstParameterType, class RealSecondParameterType>
 	class RegistratorWrapper : public RegistratorWrapperBase {
-		std::function<RealReturnType(StaticParamType&, const RealFirstParameterType&, const RealSecondParameterType&)> callback;
+		std::function<RealReturnType(StaticParamType, const RealFirstParameterType&, const RealSecondParameterType&)> callback;
 
 	public:
-		ReturnType eval(StaticParamType& res, const FirstParameterType& first, const SecondParameterType& second) {
+		ReturnType eval(StaticParamType res, const FirstParameterType& first, const SecondParameterType& second) {
 			return ReturnType(callback(res, (const RealFirstParameterType&) first, (const SecondParameterType&) second));
 		}
 
-		RegistratorWrapper(SelfType& pool, RealReturnType(*callback)(StaticParamType&, const RealFirstParameterType&, const RealSecondParameterType&)) : callback(callback) {
+		RegistratorWrapper(SelfType& pool, RealReturnType(*callback)(StaticParamType, const RealFirstParameterType&, const RealSecondParameterType&)) : callback(callback) {
 			int a = 0;
 			if(! pool.registeredFunctions.insert(std::make_pair(std::make_pair(RealFirstParameterType::typeId((const RealFirstParameterType&) a), RealSecondParameterType::typeId((const RealSecondParameterType&) a)), this)).second )
 				throw std::logic_error("Callback alreary registered.");
 		}
 	};
 
-	ReturnType dispatch(StaticParamType& res, const FirstParameterType& first, const SecondParameterType& second) {
+	ReturnType dispatch(StaticParamType res, const FirstParameterType& first, const SecondParameterType& second) {
 		typename std::map<std::pair<long long, long long>, RegistratorWrapperBase*>::iterator callback = registeredFunctions.find(std::make_pair(first.selfTypeId(), first.selfTypeId()));
 		if(callback == registeredFunctions.end()) throw std::bad_function_call();
 		return callback->second->eval(res, first, second);
diff --git a/alib2data/test-src/common/DispatchTest.cpp b/alib2data/test-src/common/DispatchTest.cpp
index bdc0370ec4395dd79a0da5e4c681e7db53597f44..a95d33509ab8b63f5da2d497ec2448fe4b560af6 100644
--- a/alib2data/test-src/common/DispatchTest.cpp
+++ b/alib2data/test-src/common/DispatchTest.cpp
@@ -210,7 +210,7 @@ namespace dispatch {
 
 // -------------------------------------------------------------------------------------------------------------------------------------------------------
 
-class TmpVisitor2 : public std::SingleDispatchFirstStaticParam<void, int, TmpBase> {
+class TmpVisitor2 : public std::SingleDispatchFirstStaticParam<void, int&, TmpBase> {
 public:
 	static void eval(int& res, const Tmp2& first) {
 		std::cout << first << std::endl;
diff --git a/alib2raw/src/tree/TreeToRawComposer.h b/alib2raw/src/tree/TreeToRawComposer.h
index f017f79c0dd2d90a0693dc80ce8374b06bc77355..4035d69ab75a59c737db5acdb53c2c3fc3a855a4 100644
--- a/alib2raw/src/tree/TreeToRawComposer.h
+++ b/alib2raw/src/tree/TreeToRawComposer.h
@@ -21,7 +21,7 @@ namespace tree {
 /**
  * This class contains methods to print XML representation of tree to the output stream.
  */
-class TreeToRawComposer : public std::SingleDispatchFirstStaticParam<void, std::deque<sax::Token>, TreeBase> {
+class TreeToRawComposer : public std::SingleDispatchFirstStaticParam<void, std::deque<sax::Token>&, TreeBase> {
 public:
 	static void compose(std::deque<sax::Token>& out, const Tree& tree);
 
diff --git a/alib2str/src/alphabet/SymbolToStringComposer.h b/alib2str/src/alphabet/SymbolToStringComposer.h
index 1c47edaefd56dea93ce0f50d69732069a2027a9f..11b584683db2acbea188c3689052f5005532895e 100644
--- a/alib2str/src/alphabet/SymbolToStringComposer.h
+++ b/alib2str/src/alphabet/SymbolToStringComposer.h
@@ -18,7 +18,7 @@ namespace alphabet {
 /**
  * This class contains methods to print XML representation of string to the output stream.
  */
-class SymbolToStringComposer : public std::SingleDispatchFirstStaticParam<void, std::ostream, SymbolBase> {
+class SymbolToStringComposer : public std::SingleDispatchFirstStaticParam<void, std::ostream&, SymbolBase> {
 public:
 	static void compose(std::ostream& output, const LabeledSymbol& symbol);
 	static void compose(std::ostream& output, const BlankSymbol& symbol);
diff --git a/alib2str/src/automaton/AutomatonToStringComposer.h b/alib2str/src/automaton/AutomatonToStringComposer.h
index 700a6e8f6d149c34c2e008c2aed89c0f8eea4868..9034a2dee1814d0fb733e3e5f244b7dca0852048 100644
--- a/alib2str/src/automaton/AutomatonToStringComposer.h
+++ b/alib2str/src/automaton/AutomatonToStringComposer.h
@@ -15,7 +15,7 @@
 
 namespace automaton {
 
-class AutomatonToStringComposer : public std::SingleDispatchFirstStaticParam<void, std::ostream, AutomatonBase> {
+class AutomatonToStringComposer : public std::SingleDispatchFirstStaticParam<void, std::ostream&, AutomatonBase> {
 	static void composeTransitionsFromState(std::ostream& out, const DFA& automaton, const State& from);
 	static void composeTransitionsFromState(std::ostream& out, const NFA& automaton, const State& from);
 	static void composeTransitionsFromState(std::ostream& out, const MultiInitialStateNFA& automaton, const State& from);
diff --git a/alib2str/src/grammar/GrammarToStringComposer.h b/alib2str/src/grammar/GrammarToStringComposer.h
index 495e9da2376a7a3e8aaaf82330f722d7aa4a8161..877ad50e4da426aa05f8ac0f2955ffb59624e5f2 100644
--- a/alib2str/src/grammar/GrammarToStringComposer.h
+++ b/alib2str/src/grammar/GrammarToStringComposer.h
@@ -8,7 +8,7 @@
 
 namespace grammar {
 
-class GrammarToStringComposer: public std::SingleDispatchFirstStaticParam<void, std::ostream, GrammarBase> {
+class GrammarToStringComposer: public std::SingleDispatchFirstStaticParam<void, std::ostream&, GrammarBase> {
 public:
 	template<class T>
 	static void composeCFLikeGrammar(std::ostream& output, const T& grammar);
diff --git a/alib2str/src/graph/GraphToStringComposer.h b/alib2str/src/graph/GraphToStringComposer.h
index 91405eec9237fca39493f96d563552f1c3cbdd19..b8ea85303a7f7649dd76e11bf5566171fb7c0582 100644
--- a/alib2str/src/graph/GraphToStringComposer.h
+++ b/alib2str/src/graph/GraphToStringComposer.h
@@ -19,7 +19,7 @@
 
 namespace graph {
 
-class GraphToStringComposer : public std::SingleDispatchFirstStaticParam<void, std::ostream, GraphBase> {
+class GraphToStringComposer : public std::SingleDispatchFirstStaticParam<void, std::ostream&, GraphBase> {
 private:
 	static void composeNode(std::ostream& out, const Node &node);
 	static void composeEdge(std::ostream& out, const DirectedEdge &edge);
diff --git a/alib2str/src/label/LabelToStringComposer.h b/alib2str/src/label/LabelToStringComposer.h
index 8b88feb659fd1ab9c7ed9a5cad2ed5371cdfb38f..b85b6048f88b2f3ece16efabf3feea03ac8d2fb4 100644
--- a/alib2str/src/label/LabelToStringComposer.h
+++ b/alib2str/src/label/LabelToStringComposer.h
@@ -18,7 +18,7 @@ namespace label {
 /**
  * This class contains methods to print XML representation of string to the output stream.
  */
-class LabelToStringComposer : public std::SingleDispatchFirstStaticParam<void, std::ostream, LabelBase> {
+class LabelToStringComposer : public std::SingleDispatchFirstStaticParam<void, std::ostream&, LabelBase> {
 public:
 	static void compose(std::ostream&, const PrimitiveLabel& label);
 	static void compose(std::ostream&, const HexavigesimalLabel& label);
diff --git a/alib2str/src/primitive/PrimitiveToStringComposer.h b/alib2str/src/primitive/PrimitiveToStringComposer.h
index da37f1db94e402ef69a888c8a1c200d92ec3a30e..15a7ed353b2559db60f56dbb1329541f791c3a36 100644
--- a/alib2str/src/primitive/PrimitiveToStringComposer.h
+++ b/alib2str/src/primitive/PrimitiveToStringComposer.h
@@ -18,7 +18,7 @@ namespace primitive {
 /**
  * This class contains methods to print XML representation of string to the output stream.
  */
-class PrimitiveToStringComposer : public std::SingleDispatchFirstStaticParam<void, std::ostream, PrimitiveBase> {
+class PrimitiveToStringComposer : public std::SingleDispatchFirstStaticParam<void, std::ostream&, PrimitiveBase> {
 public:
 	static void compose(std::ostream&, const Integer& primitive);
 	static void compose(std::ostream&, const String& primitive);
diff --git a/alib2str/src/regexp/RegExpToStringComposer.h b/alib2str/src/regexp/RegExpToStringComposer.h
index 683d2ff6073c14ac402bdf74a6b84eae86ae2e32..92da2f7428af7a53a6f5c0aa0a1617829a7fb036 100644
--- a/alib2str/src/regexp/RegExpToStringComposer.h
+++ b/alib2str/src/regexp/RegExpToStringComposer.h
@@ -16,7 +16,7 @@
 
 namespace regexp {
 
-class RegExpToStringComposer : public std::SingleDispatchFirstStaticParam<void, std::ostream, RegExpBase>, UnboundedRegExpElement::const_visitor_type, FormalRegExpElement::const_visitor_type {
+class RegExpToStringComposer : public std::SingleDispatchFirstStaticParam<void, std::ostream&, RegExpBase>, UnboundedRegExpElement::const_visitor_type, FormalRegExpElement::const_visitor_type {
 private:
 	void Visit(void*, const UnboundedRegExpAlternation& alternation) const;
 	void Visit(void*, const UnboundedRegExpConcatenation& concatenation) const;
diff --git a/alib2str/src/string/StringToStringComposer.h b/alib2str/src/string/StringToStringComposer.h
index 7119954e8e639f014ac803e648d74cb84013825e..aef54dd02631460ddd720aca39c41a9539a62184 100644
--- a/alib2str/src/string/StringToStringComposer.h
+++ b/alib2str/src/string/StringToStringComposer.h
@@ -18,7 +18,7 @@ namespace string {
 /**
  * This class contains methods to print XML representation of string to the output stream.
  */
-class StringToStringComposer: public std::SingleDispatchFirstStaticParam<void, std::ostream, StringBase> {
+class StringToStringComposer: public std::SingleDispatchFirstStaticParam<void, std::ostream&, StringBase> {
 public:
 	static void compose(std::ostream&, const LinearString& string);
 	static void compose(std::ostream&, const CyclicString& string);
diff --git a/astat2/src/AutomataStat.cpp b/astat2/src/AutomataStat.cpp
index 3fc714af9e708e489cd8695e9f8530bef4853b1b..436c6ceb81395071c9b3da1381bb11c94a28b5fd 100644
--- a/astat2/src/AutomataStat.cpp
+++ b/astat2/src/AutomataStat.cpp
@@ -18,7 +18,7 @@
 #include <iostream>
 
 void AutomataStat::stat(const automaton::Automaton& automaton, const AutomataSettings& settings) {
-	automaton.getData().Accept((void*) &settings, AutomataStat::AUTOMATA_STAT);
+	getInstance().dispatch(automaton.getData(), settings);
 }
 
 void AutomataStat::stat(const automaton::NFA& automaton, const AutomataSettings& settings) {
@@ -98,6 +98,8 @@ void AutomataStat::stat(const automaton::NFA& automaton, const AutomataSettings&
 	}
 }
 
+auto AutomataStatNFA = AutomataStat::RegistratorWrapper<void, automaton::NFA>(AutomataStat::getInstance(), AutomataStat::stat);
+
 void AutomataStat::stat(const automaton::DFA& automaton, const AutomataSettings& settings) {
 	switch(settings.states) {
 	case PrintingOptions::PRINT:
@@ -175,83 +177,5 @@ void AutomataStat::stat(const automaton::DFA& automaton, const AutomataSettings&
 	}
 }
 
-void AutomataStat::Visit(void*, const automaton::EpsilonNFA&) const {
-	throw exception::AlibException("Unsupported automaton type EpsilonNFA");
-}
-
-void AutomataStat::Visit(void*, const automaton::MultiInitialStateNFA&) const {
-	throw exception::AlibException("Unsupported automaton type EpsilonNFA");
-}
-
-void AutomataStat::Visit(void* data, const automaton::NFA& automaton) const {
-	const AutomataSettings& in = *((const AutomataSettings*) data);
-	this->stat(automaton, in);
-}
-
-void AutomataStat::Visit(void* data, const automaton::DFA& automaton) const {
-	const AutomataSettings& in = *((const AutomataSettings*) data);
-	this->stat(automaton, in);
-}
-
-void AutomataStat::Visit(void*, const automaton::ExtendedNFA&) const {
-	throw exception::AlibException("Unsupported automaton type ExtendedNFA");
-}
-
-void AutomataStat::Visit(void*, const automaton::CompactNFA&) const {
-	throw exception::AlibException("Unsupported automaton type CompactNFA");
-}
-
-void AutomataStat::Visit(void*, const automaton::DPDA&) const {
-	throw exception::AlibException("Unsupported automaton type DPDAAutomaton");
-}
-
-void AutomataStat::Visit(void*, const automaton::SinglePopDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
-}
-
-void AutomataStat::Visit(void*, const automaton::InputDrivenDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type InputDrivenDPDA");
-}
-
-void AutomataStat::Visit(void*, const automaton::InputDrivenNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
-}
-
-void AutomataStat::Visit(void*, const automaton::VisiblyPushdownDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA");
-}
-
-void AutomataStat::Visit(void*, const automaton::VisiblyPushdownNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
-}
-
-void AutomataStat::Visit(void*, const automaton::RealTimeHeightDeterministicDPDA&) const {
-	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA");
-}
-
-void AutomataStat::Visit(void*, const automaton::RealTimeHeightDeterministicNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA");
-}
-
-void AutomataStat::Visit(void*, const automaton::NPDA&) const {
-	throw exception::AlibException("Unsupported automaton type NPDA");
-}
-
-void AutomataStat::Visit(void*, const automaton::SinglePopNPDA&) const {
-	throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
-}
-
-void AutomataStat::Visit(void*, const automaton::OneTapeDTM&) const {
-	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
-}
-
-void AutomataStat::Visit(void*, const automaton::DFTA&) const {
-	throw exception::AlibException("Unsupported automaton type DFTA");
-}
-
-void AutomataStat::Visit(void*, const automaton::NFTA&) const {
-	throw exception::AlibException("Unsupported automaton type NFTA");
-}
-
-const AutomataStat AutomataStat::AUTOMATA_STAT;
+auto AutomataStatDFA = AutomataStat::RegistratorWrapper<void, automaton::DFA>(AutomataStat::getInstance(), AutomataStat::stat);
 
diff --git a/astat2/src/AutomataStat.h b/astat2/src/AutomataStat.h
index d3531ab8559c4f2ad87c4d0ff7d9d5bd4ebc7bcd..f8fa347612ed441961ee372f76d3f0513f57f4d6 100644
--- a/astat2/src/AutomataStat.h
+++ b/astat2/src/AutomataStat.h
@@ -8,6 +8,7 @@
 #ifndef AUTOMATA_STAT_H_
 #define AUTOMATA_STAT_H_
 
+#include <common/multipleDispatch.hpp>
 #include <algorithm>
 #include <deque>
 #include <set>
@@ -17,37 +18,17 @@
 
 #include "AutomataSettings.h"
 
-class AutomataStat : public automaton::VisitableAutomatonBase::const_visitor_type {
+class AutomataStat : public std::SingleDispatchLastStaticParam<void, automaton::AutomatonBase, const AutomataSettings&> {
 public:
-	AutomataStat() {}
-
 	static void stat(const automaton::Automaton& automaton, const AutomataSettings& settings);
 
 	static void stat(const automaton::NFA& automaton, const AutomataSettings& settings);
 	static void stat(const automaton::DFA& automaton, const AutomataSettings& settings);
 
-private:
-	void Visit(void*, const automaton::EpsilonNFA& automaton) const;
-	void Visit(void*, const automaton::MultiInitialStateNFA& automaton) const;
-	void Visit(void*, const automaton::NFA& automaton) const;
-	void Visit(void*, const automaton::DFA& automaton) const;
-	void Visit(void*, const automaton::ExtendedNFA& automaton) const;
-	void Visit(void*, const automaton::CompactNFA& automaton) const;
-	void Visit(void*, const automaton::DPDA& automaton) const;
-	void Visit(void*, const automaton::SinglePopDPDA& automaton) const;
-	void Visit(void*, const automaton::InputDrivenDPDA& automaton) const;
-	void Visit(void*, const automaton::InputDrivenNPDA& automaton) const;
-	void Visit(void*, const automaton::VisiblyPushdownDPDA& automaton) const;
-	void Visit(void*, const automaton::VisiblyPushdownNPDA& automaton) const;
-	void Visit(void*, const automaton::RealTimeHeightDeterministicDPDA& automaton) const;
-	void Visit(void*, const automaton::RealTimeHeightDeterministicNPDA& automaton) const;
-	void Visit(void*, const automaton::NPDA& automaton) const;
-	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
-	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
-	void Visit(void*, const automaton::NFTA& automaton) const;
-	void Visit(void*, const automaton::DFTA& automaton) const;
-
-	static const AutomataStat AUTOMATA_STAT;
+	static AutomataStat& getInstance() {
+		static AutomataStat res;
+		return res;
+	}
 };
 
 #endif /* AUTOMATA_STAT_H_ */