From 71e67ea2bc8b985a6361ce5ea27f363eeb26ead1 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Sat, 15 Aug 2015 13:21:54 +0200
Subject: [PATCH] continue with grammar properties

---
 .../grammar/properties/IsLanguageEmpty.cpp    | 85 +++----------------
 .../src/grammar/properties/IsLanguageEmpty.h  | 26 ++----
 .../IsLanguageGeneratingEpsilon.cpp           | 85 +++----------------
 .../properties/IsLanguageGeneratingEpsilon.h  | 26 ++----
 .../properties/NonterminalUnitRuleCycle.cpp   | 85 +++----------------
 .../properties/NonterminalUnitRuleCycle.h     | 26 ++----
 .../properties/NullableNonterminals.cpp       | 85 +++----------------
 .../grammar/properties/NullableNonterminals.h | 26 ++----
 .../properties/ProductiveNonterminals.cpp     | 85 +++----------------
 .../properties/ProductiveNonterminals.h       | 26 ++----
 .../grammar/properties/UnreachableSymbols.cpp | 85 +++----------------
 .../grammar/properties/UnreachableSymbols.h   | 26 ++----
 .../src/regexp/properties/RegExpEpsilon.h     |  3 +-
 13 files changed, 103 insertions(+), 566 deletions(-)

diff --git a/alib2algo/src/grammar/properties/IsLanguageEmpty.cpp b/alib2algo/src/grammar/properties/IsLanguageEmpty.cpp
index 2cf3e291bf..b1d5e6b6cd 100644
--- a/alib2algo/src/grammar/properties/IsLanguageEmpty.cpp
+++ b/alib2algo/src/grammar/properties/IsLanguageEmpty.cpp
@@ -28,85 +28,20 @@ bool IsLanguageEmpty::isLanguageEmpty( const T & grammar ) {
 	return grammar::properties::ProductiveNonterminals::getProductiveNonterminals( grammar ).count( grammar.getInitialSymbol( ) );
 }
 
-template bool IsLanguageEmpty::isLanguageEmpty( const grammar::CFG & grammar );
-template bool IsLanguageEmpty::isLanguageEmpty( const grammar::EpsilonFreeCFG & grammar );
-template bool IsLanguageEmpty::isLanguageEmpty( const grammar::GNF & grammar );
-template bool IsLanguageEmpty::isLanguageEmpty( const grammar::CNF & grammar );
-template bool IsLanguageEmpty::isLanguageEmpty( const grammar::LG & grammar );
-template bool IsLanguageEmpty::isLanguageEmpty( const grammar::LeftLG & grammar );
-template bool IsLanguageEmpty::isLanguageEmpty( const grammar::LeftRG & grammar );
-template bool IsLanguageEmpty::isLanguageEmpty( const grammar::RightLG & grammar );
-template bool IsLanguageEmpty::isLanguageEmpty( const grammar::RightRG & grammar );
+auto IsLanguageEmptyCFG = IsLanguageEmpty::RegistratorWrapper<bool, grammar::CFG>(IsLanguageEmpty::getInstance(), IsLanguageEmpty::isLanguageEmpty);
+auto IsLanguageEmptyEpsilonFreeCFG = IsLanguageEmpty::RegistratorWrapper<bool, grammar::EpsilonFreeCFG>(IsLanguageEmpty::getInstance(), IsLanguageEmpty::isLanguageEmpty);
+auto IsLanguageEmptyGNF = IsLanguageEmpty::RegistratorWrapper<bool, grammar::GNF>(IsLanguageEmpty::getInstance(), IsLanguageEmpty::isLanguageEmpty);
+auto IsLanguageEmptyCNF = IsLanguageEmpty::RegistratorWrapper<bool, grammar::CNF>(IsLanguageEmpty::getInstance(), IsLanguageEmpty::isLanguageEmpty);
+auto IsLanguageEmptyLG = IsLanguageEmpty::RegistratorWrapper<bool, grammar::LG>(IsLanguageEmpty::getInstance(), IsLanguageEmpty::isLanguageEmpty);
+auto IsLanguageEmptyLeftLG = IsLanguageEmpty::RegistratorWrapper<bool, grammar::LeftLG>(IsLanguageEmpty::getInstance(), IsLanguageEmpty::isLanguageEmpty);
+auto IsLanguageEmptyLeftRG = IsLanguageEmpty::RegistratorWrapper<bool, grammar::LeftRG>(IsLanguageEmpty::getInstance(), IsLanguageEmpty::isLanguageEmpty);
+auto IsLanguageEmptyRightLG = IsLanguageEmpty::RegistratorWrapper<bool, grammar::RightLG>(IsLanguageEmpty::getInstance(), IsLanguageEmpty::isLanguageEmpty);
+auto IsLanguageEmptyRightRG = IsLanguageEmpty::RegistratorWrapper<bool, grammar::RightRG>(IsLanguageEmpty::getInstance(), IsLanguageEmpty::isLanguageEmpty);
 
 bool IsLanguageEmpty::isLanguageEmpty(const grammar::Grammar& grammar) {
-	bool out;
-	grammar.getData().Accept((void*) &out, IsLanguageEmpty::IS_LANGUAGE_EMPTY);
-	return out;
+	return getInstance().dispatch(grammar.getData());
 }
 
-void IsLanguageEmpty::Visit(void* data, const grammar::LeftLG& grammar) const {
-	bool & out = *((bool*) data);
-	out = this->isLanguageEmpty(grammar);
-}
-
-void IsLanguageEmpty::Visit(void* data, const grammar::LeftRG& grammar) const {
-	bool & out = *((bool*) data);
-	out = this->isLanguageEmpty(grammar);
-}
-
-void IsLanguageEmpty::Visit(void* data, const grammar::RightLG& grammar) const {
-	bool & out = *((bool*) data);
-	out = this->isLanguageEmpty(grammar);
-}
-
-void IsLanguageEmpty::Visit(void* data, const grammar::RightRG& grammar) const {
-	bool & out = *((bool*) data);
-	out = this->isLanguageEmpty(grammar);
-}
-
-void IsLanguageEmpty::Visit(void* data, const grammar::LG& grammar) const {
-	bool & out = *((bool*) data);
-	out = this->isLanguageEmpty(grammar);
-}
-
-void IsLanguageEmpty::Visit(void* data, const grammar::CFG& grammar) const {
-	bool & out = *((bool*) data);
-	out = this->isLanguageEmpty(grammar);
-}
-
-void IsLanguageEmpty::Visit(void* data, const grammar::EpsilonFreeCFG& grammar) const {
-	bool & out = *((bool*) data);
-	out = this->isLanguageEmpty(grammar);
-}
-
-void IsLanguageEmpty::Visit(void* data, const grammar::CNF& grammar) const {
-	bool & out = *((bool*) data);
-	out = this->isLanguageEmpty(grammar);
-}
-
-void IsLanguageEmpty::Visit(void* data, const grammar::GNF& grammar) const {
-	bool & out = *((bool*) data);
-	out = this->isLanguageEmpty(grammar);
-}
-
-void IsLanguageEmpty::Visit(void*, const grammar::CSG&) const {
-	throw exception::AlibException("Unsupported grammar type CSG");
-}
-
-void IsLanguageEmpty::Visit(void*, const grammar::NonContractingGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type NonConctractingGrammar");
-}
-
-void IsLanguageEmpty::Visit(void*, const grammar::ContextPreservingUnrestrictedGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type ContextPreservingUnrestrictedGrammar");
-}
-
-void IsLanguageEmpty::Visit(void*, const grammar::UnrestrictedGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type UnrestrictedGrammar");
-}
-
-const IsLanguageEmpty IsLanguageEmpty::IS_LANGUAGE_EMPTY;
-
 } /* namespace properties */
 
 } /* namespace grammar */
diff --git a/alib2algo/src/grammar/properties/IsLanguageEmpty.h b/alib2algo/src/grammar/properties/IsLanguageEmpty.h
index 0921e4f4ad..02d8837bae 100644
--- a/alib2algo/src/grammar/properties/IsLanguageEmpty.h
+++ b/alib2algo/src/grammar/properties/IsLanguageEmpty.h
@@ -8,6 +8,8 @@
 #ifndef IS_LANGUAGE_EMPTY_H_
 #define IS_LANGUAGE_EMPTY_H_
 
+#include <common/multipleDispatch.hpp>
+
 #include <grammar/Grammar.h>
 
 namespace grammar {
@@ -17,10 +19,8 @@ namespace properties {
 /**
  * Implements algorithms from Melichar, chapter 3.3
  */
-class IsLanguageEmpty : public grammar::VisitableGrammarBase::const_visitor_type {
+class IsLanguageEmpty : public std::SingleDispatch<bool, grammar::GrammarBase> {
 public:
-	IsLanguageEmpty() {}
-
 	static bool isLanguageEmpty( const grammar::Grammar & grammar );
 
 	/*
@@ -32,22 +32,10 @@ public:
 	template<class T>
 	static bool isLanguageEmpty( const T & grammar );
 
-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 IsLanguageEmpty IS_LANGUAGE_EMPTY;
+	static IsLanguageEmpty& getInstance() {
+		static IsLanguageEmpty res;
+		return res;
+	}
 };
 
 } /* namespace properties */
diff --git a/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.cpp b/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.cpp
index eedaab2b1c..3046cfd991 100644
--- a/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.cpp
+++ b/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.cpp
@@ -28,85 +28,20 @@ bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon( const T & grammar
 	return grammar::properties::NullableNonterminals::getNullableNonterminals( grammar ).count( grammar.getInitialSymbol( ) );
 }
 
-template bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon( const grammar::CFG & grammar );
-template bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon( const grammar::EpsilonFreeCFG & grammar );
-template bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon( const grammar::GNF & grammar );
-template bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon( const grammar::CNF & grammar );
-template bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon( const grammar::LG & grammar );
-template bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon( const grammar::LeftLG & grammar );
-template bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon( const grammar::LeftRG & grammar );
-template bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon( const grammar::RightLG & grammar );
-template bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon( const grammar::RightRG & grammar );
+auto IsLanguageGeneratingEpsilonCFG = IsLanguageGeneratingEpsilon::RegistratorWrapper<bool, grammar::CFG>(IsLanguageGeneratingEpsilon::getInstance(), IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon);
+auto IsLanguageGeneratingEpsilonEpsilonFreeCFG = IsLanguageGeneratingEpsilon::RegistratorWrapper<bool, grammar::EpsilonFreeCFG>(IsLanguageGeneratingEpsilon::getInstance(), IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon);
+auto IsLanguageGeneratingEpsilonGNF = IsLanguageGeneratingEpsilon::RegistratorWrapper<bool, grammar::GNF>(IsLanguageGeneratingEpsilon::getInstance(), IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon);
+auto IsLanguageGeneratingEpsilonCNF = IsLanguageGeneratingEpsilon::RegistratorWrapper<bool, grammar::CNF>(IsLanguageGeneratingEpsilon::getInstance(), IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon);
+auto IsLanguageGeneratingEpsilonLG = IsLanguageGeneratingEpsilon::RegistratorWrapper<bool, grammar::LG>(IsLanguageGeneratingEpsilon::getInstance(), IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon);
+auto IsLanguageGeneratingEpsilonLeftLG = IsLanguageGeneratingEpsilon::RegistratorWrapper<bool, grammar::LeftLG>(IsLanguageGeneratingEpsilon::getInstance(), IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon);
+auto IsLanguageGeneratingEpsilonLeftRG = IsLanguageGeneratingEpsilon::RegistratorWrapper<bool, grammar::LeftRG>(IsLanguageGeneratingEpsilon::getInstance(), IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon);
+auto IsLanguageGeneratingEpsilonRightLG = IsLanguageGeneratingEpsilon::RegistratorWrapper<bool, grammar::RightLG>(IsLanguageGeneratingEpsilon::getInstance(), IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon);
+auto IsLanguageGeneratingEpsilonRightRG = IsLanguageGeneratingEpsilon::RegistratorWrapper<bool, grammar::RightRG>(IsLanguageGeneratingEpsilon::getInstance(), IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon);
 
 bool IsLanguageGeneratingEpsilon::isLanguageGeneratingEpsilon(const grammar::Grammar& grammar) {
-	bool out;
-	grammar.getData().Accept((void*) &out, IsLanguageGeneratingEpsilon::IS_LANGUAGE_GENERATING_EPSILON);
-	return out;
+	return getInstance().dispatch(grammar.getData());
 }
 
-void IsLanguageGeneratingEpsilon::Visit(void* data, const grammar::LeftLG& grammar) const {
-	bool & out = *((bool*) data);
-	out = std::move(this->isLanguageGeneratingEpsilon(grammar));
-}
-
-void IsLanguageGeneratingEpsilon::Visit(void* data, const grammar::LeftRG& grammar) const {
-	bool & out = *((bool*) data);
-	out = std::move(this->isLanguageGeneratingEpsilon(grammar));
-}
-
-void IsLanguageGeneratingEpsilon::Visit(void* data, const grammar::RightLG& grammar) const {
-	bool & out = *((bool*) data);
-	out = std::move(this->isLanguageGeneratingEpsilon(grammar));
-}
-
-void IsLanguageGeneratingEpsilon::Visit(void* data, const grammar::RightRG& grammar) const {
-	bool & out = *((bool*) data);
-	out = std::move(this->isLanguageGeneratingEpsilon(grammar));
-}
-
-void IsLanguageGeneratingEpsilon::Visit(void* data, const grammar::LG& grammar) const {
-	bool & out = *((bool*) data);
-	out = std::move(this->isLanguageGeneratingEpsilon(grammar));
-}
-
-void IsLanguageGeneratingEpsilon::Visit(void* data, const grammar::CFG& grammar) const {
-	bool & out = *((bool*) data);
-	out = std::move(this->isLanguageGeneratingEpsilon(grammar));
-}
-
-void IsLanguageGeneratingEpsilon::Visit(void* data, const grammar::EpsilonFreeCFG& grammar) const {
-	bool & out = *((bool*) data);
-	out = std::move(this->isLanguageGeneratingEpsilon(grammar));
-}
-
-void IsLanguageGeneratingEpsilon::Visit(void* data, const grammar::CNF& grammar) const {
-	bool & out = *((bool*) data);
-	out = std::move(this->isLanguageGeneratingEpsilon(grammar));
-}
-
-void IsLanguageGeneratingEpsilon::Visit(void* data, const grammar::GNF& grammar) const {
-	bool & out = *((bool*) data);
-	out = std::move(this->isLanguageGeneratingEpsilon(grammar));
-}
-
-void IsLanguageGeneratingEpsilon::Visit(void*, const grammar::CSG&) const {
-	throw exception::AlibException("Unsupported grammar type CSG");
-}
-
-void IsLanguageGeneratingEpsilon::Visit(void*, const grammar::NonContractingGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type NonConctractingGrammar");
-}
-
-void IsLanguageGeneratingEpsilon::Visit(void*, const grammar::ContextPreservingUnrestrictedGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type ContextPreservingUnrestrictedGrammar");
-}
-
-void IsLanguageGeneratingEpsilon::Visit(void*, const grammar::UnrestrictedGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type UnrestrictedGrammar");
-}
-
-const IsLanguageGeneratingEpsilon IsLanguageGeneratingEpsilon::IS_LANGUAGE_GENERATING_EPSILON;
-
 } /* namespace properties */
 
 } /* namespace grammar */
diff --git a/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.h b/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.h
index ef87b98b7c..9e082a97be 100644
--- a/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.h
+++ b/alib2algo/src/grammar/properties/IsLanguageGeneratingEpsilon.h
@@ -8,6 +8,8 @@
 #ifndef IS_LANGUAGE_GENERATING_EPSILON_H_
 #define IS_LANGUAGE_GENERATING_EPSILON_H_
 
+#include <common/multipleDispatch.hpp>
+
 #include <grammar/Grammar.h>
 
 namespace grammar {
@@ -17,10 +19,8 @@ namespace properties {
 /**
  * Implements algorithms from Melichar, chapter 3.3
  */
-class IsLanguageGeneratingEpsilon : public grammar::VisitableGrammarBase::const_visitor_type {
+class IsLanguageGeneratingEpsilon : public std::SingleDispatch<bool, grammar::GrammarBase> {
 public:
-	IsLanguageGeneratingEpsilon() {}
-
 	static bool isLanguageGeneratingEpsilon( const grammar::Grammar & grammar );
 
 	/*
@@ -32,22 +32,10 @@ public:
 	template<class T>
 	static bool isLanguageGeneratingEpsilon( const T & grammar );
 
-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 IsLanguageGeneratingEpsilon IS_LANGUAGE_GENERATING_EPSILON;
+	static IsLanguageGeneratingEpsilon& getInstance() {
+		static IsLanguageGeneratingEpsilon res;
+		return res;
+	}
 };
 
 } /* namespace properties */
diff --git a/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.cpp b/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.cpp
index 2534518e51..7f28661b29 100644
--- a/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.cpp
+++ b/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.cpp
@@ -55,85 +55,20 @@ std::set<alphabet::Symbol> NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle
 	return Ni.at(i);
 }
 
-template std::set<alphabet::Symbol> NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(const grammar::CFG& grammar, const alphabet::Symbol& nonterminal);
-template std::set<alphabet::Symbol> NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(const grammar::EpsilonFreeCFG& grammar, const alphabet::Symbol& nonterminal);
-template std::set<alphabet::Symbol> NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(const grammar::GNF& grammar, const alphabet::Symbol& nonterminal);
-template std::set<alphabet::Symbol> NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(const grammar::CNF& grammar, const alphabet::Symbol& nonterminal);
-template std::set<alphabet::Symbol> NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(const grammar::LG& grammar, const alphabet::Symbol& nonterminal);
-template std::set<alphabet::Symbol> NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(const grammar::LeftLG& grammar, const alphabet::Symbol& nonterminal);
-template std::set<alphabet::Symbol> NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(const grammar::LeftRG& grammar, const alphabet::Symbol& nonterminal);
-template std::set<alphabet::Symbol> NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(const grammar::RightLG& grammar, const alphabet::Symbol& nonterminal);
-template std::set<alphabet::Symbol> NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(const grammar::RightRG& grammar, const alphabet::Symbol& nonterminal);
+auto NonterminalUnitRuleCycleCFG = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CFG>(NonterminalUnitRuleCycle::getInstance(), NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle);
+auto NonterminalUnitRuleCycleEpsilonFreeCFG = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG>(NonterminalUnitRuleCycle::getInstance(), NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle);
+auto NonterminalUnitRuleCycleGNF = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF>(NonterminalUnitRuleCycle::getInstance(), NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle);
+auto NonterminalUnitRuleCycleCNF = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CNF>(NonterminalUnitRuleCycle::getInstance(), NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle);
+auto NonterminalUnitRuleCycleLG = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::LG>(NonterminalUnitRuleCycle::getInstance(), NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle);
+auto NonterminalUnitRuleCycleLeftLG = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::LeftLG>(NonterminalUnitRuleCycle::getInstance(), NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle);
+auto NonterminalUnitRuleCycleLeftRG = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::LeftRG>(NonterminalUnitRuleCycle::getInstance(), NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle);
+auto NonterminalUnitRuleCycleRightLG = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightLG>(NonterminalUnitRuleCycle::getInstance(), NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle);
+auto NonterminalUnitRuleCycleRightRG = NonterminalUnitRuleCycle::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightRG>(NonterminalUnitRuleCycle::getInstance(), NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle);
 
 std::set<alphabet::Symbol> NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(const grammar::Grammar& grammar, const alphabet::Symbol& nonterminal) {
-	std::pair<alphabet::Symbol, std::set<alphabet::Symbol>> out(nonterminal, {});
-	grammar.getData().Accept((void*) &out, NonterminalUnitRuleCycle::NONTERMINAL_UNIT_RULE_CYCLE);
-	return out.second;
+	return getInstance().dispatch(grammar.getData(), nonterminal);
 }
 
-void NonterminalUnitRuleCycle::Visit(void* data, const grammar::LeftLG& grammar) const {
-	std::pair<alphabet::Symbol, std::set<alphabet::Symbol>> & out = *((std::pair<alphabet::Symbol, std::set<alphabet::Symbol>>*) data);
-	out.second = std::move(this->getNonterminalUnitRuleCycle(grammar, out.first));
-}
-
-void NonterminalUnitRuleCycle::Visit(void* data, const grammar::LeftRG& grammar) const {
-	std::pair<alphabet::Symbol, std::set<alphabet::Symbol>> & out = *((std::pair<alphabet::Symbol, std::set<alphabet::Symbol>>*) data);
-	out.second = std::move(this->getNonterminalUnitRuleCycle(grammar, out.first));
-}
-
-void NonterminalUnitRuleCycle::Visit(void* data, const grammar::RightLG& grammar) const {
-	std::pair<alphabet::Symbol, std::set<alphabet::Symbol>> & out = *((std::pair<alphabet::Symbol, std::set<alphabet::Symbol>>*) data);
-	out.second = std::move(this->getNonterminalUnitRuleCycle(grammar, out.first));
-}
-
-void NonterminalUnitRuleCycle::Visit(void* data, const grammar::RightRG& grammar) const {
-	std::pair<alphabet::Symbol, std::set<alphabet::Symbol>> & out = *((std::pair<alphabet::Symbol, std::set<alphabet::Symbol>>*) data);
-	out.second = std::move(this->getNonterminalUnitRuleCycle(grammar, out.first));
-}
-
-void NonterminalUnitRuleCycle::Visit(void* data, const grammar::LG& grammar) const {
-	std::pair<alphabet::Symbol, std::set<alphabet::Symbol>> & out = *((std::pair<alphabet::Symbol, std::set<alphabet::Symbol>>*) data);
-	out.second = std::move(this->getNonterminalUnitRuleCycle(grammar, out.first));
-}
-
-void NonterminalUnitRuleCycle::Visit(void* data, const grammar::CFG& grammar) const {
-	std::pair<alphabet::Symbol, std::set<alphabet::Symbol>> & out = *((std::pair<alphabet::Symbol, std::set<alphabet::Symbol>>*) data);
-	out.second = std::move(this->getNonterminalUnitRuleCycle(grammar, out.first));
-}
-
-void NonterminalUnitRuleCycle::Visit(void* data, const grammar::EpsilonFreeCFG& grammar) const {
-	std::pair<alphabet::Symbol, std::set<alphabet::Symbol>> & out = *((std::pair<alphabet::Symbol, std::set<alphabet::Symbol>>*) data);
-	out.second = std::move(this->getNonterminalUnitRuleCycle(grammar, out.first));
-}
-
-void NonterminalUnitRuleCycle::Visit(void* data, const grammar::CNF& grammar) const {
-	std::pair<alphabet::Symbol, std::set<alphabet::Symbol>> & out = *((std::pair<alphabet::Symbol, std::set<alphabet::Symbol>>*) data);
-	out.second = std::move(this->getNonterminalUnitRuleCycle(grammar, out.first));
-}
-
-void NonterminalUnitRuleCycle::Visit(void* data, const grammar::GNF& grammar) const {
-	std::pair<alphabet::Symbol, std::set<alphabet::Symbol>> & out = *((std::pair<alphabet::Symbol, std::set<alphabet::Symbol>>*) data);
-	out.second = std::move(this->getNonterminalUnitRuleCycle(grammar, out.first));
-}
-
-void NonterminalUnitRuleCycle::Visit(void*, const grammar::CSG&) const {
-	throw exception::AlibException("Unsupported grammar type CSG");
-}
-
-void NonterminalUnitRuleCycle::Visit(void*, const grammar::NonContractingGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type NonConctractingGrammar");
-}
-
-void NonterminalUnitRuleCycle::Visit(void*, const grammar::ContextPreservingUnrestrictedGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type ContextPreservingUnrestrictedGrammar");
-}
-
-void NonterminalUnitRuleCycle::Visit(void*, const grammar::UnrestrictedGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type UnrestrictedGrammar");
-}
-
-const NonterminalUnitRuleCycle NonterminalUnitRuleCycle::NONTERMINAL_UNIT_RULE_CYCLE;
-
 } /* namespace properties */
 
 } /* namespace grammar */
diff --git a/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.h b/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.h
index c5802dc48d..62c9206b94 100644
--- a/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.h
+++ b/alib2algo/src/grammar/properties/NonterminalUnitRuleCycle.h
@@ -8,6 +8,8 @@
 #ifndef NONTERMINAL_UNIT_RULE_CYCLE_H_
 #define NONTERMINAL_UNIT_RULE_CYCLE_H_
 
+#include <common/multipleDispatch.hpp>
+
 #include <grammar/Grammar.h>
 #include <alphabet/Symbol.h>
 
@@ -18,10 +20,8 @@ namespace properties {
 /**
  * Implements algorithms from Melichar, chapter 3.3
  */
-class NonterminalUnitRuleCycle : public grammar::VisitableGrammarBase::const_visitor_type {
+class NonterminalUnitRuleCycle : public std::SingleDispatchLastStaticParam<std::set<alphabet::Symbol>, grammar::GrammarBase, const alphabet::Symbol> {
 public:
-	NonterminalUnitRuleCycle() {}
-
 	static std::set<alphabet::Symbol> getNonterminalUnitRuleCycle( const grammar::Grammar & grammar, const alphabet::Symbol& nonterminal );
 
 	/**
@@ -36,22 +36,10 @@ public:
 	template<class T>
 	static std::set<alphabet::Symbol> getNonterminalUnitRuleCycle(const T& grammar, const alphabet::Symbol& nonterminal);
 
-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 NonterminalUnitRuleCycle NONTERMINAL_UNIT_RULE_CYCLE;
+	static NonterminalUnitRuleCycle& getInstance() {
+		static NonterminalUnitRuleCycle res;
+		return res;
+	}
 };
 
 } /* namespace properties */
diff --git a/alib2algo/src/grammar/properties/NullableNonterminals.cpp b/alib2algo/src/grammar/properties/NullableNonterminals.cpp
index 01fcae4083..3749bf0c4b 100644
--- a/alib2algo/src/grammar/properties/NullableNonterminals.cpp
+++ b/alib2algo/src/grammar/properties/NullableNonterminals.cpp
@@ -51,85 +51,20 @@ std::set<alphabet::Symbol> NullableNonterminals::getNullableNonterminals(const T
 	return Ni.at(i);
 }
 
-template std::set<alphabet::Symbol> NullableNonterminals::getNullableNonterminals( const grammar::CFG& grammar );
-template std::set<alphabet::Symbol> NullableNonterminals::getNullableNonterminals( const grammar::EpsilonFreeCFG& grammar );
-template std::set<alphabet::Symbol> NullableNonterminals::getNullableNonterminals( const grammar::GNF& grammar );
-template std::set<alphabet::Symbol> NullableNonterminals::getNullableNonterminals( const grammar::CNF& grammar );
-template std::set<alphabet::Symbol> NullableNonterminals::getNullableNonterminals( const grammar::LG& grammar );
-template std::set<alphabet::Symbol> NullableNonterminals::getNullableNonterminals( const grammar::LeftLG& grammar );
-template std::set<alphabet::Symbol> NullableNonterminals::getNullableNonterminals( const grammar::LeftRG& grammar );
-template std::set<alphabet::Symbol> NullableNonterminals::getNullableNonterminals( const grammar::RightLG& grammar );
-template std::set<alphabet::Symbol> NullableNonterminals::getNullableNonterminals( const grammar::RightRG& grammar );
+auto NullableNonterminalsCFG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CFG>(NullableNonterminals::getInstance(), NullableNonterminals::getNullableNonterminals);
+auto NullableNonterminalsEpsilonFreeCFG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG>(NullableNonterminals::getInstance(), NullableNonterminals::getNullableNonterminals);
+auto NullableNonterminalsGNF = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF>(NullableNonterminals::getInstance(), NullableNonterminals::getNullableNonterminals);
+auto NullableNonterminalsCNF = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CNF>(NullableNonterminals::getInstance(), NullableNonterminals::getNullableNonterminals);
+auto NullableNonterminalsLG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::LG>(NullableNonterminals::getInstance(), NullableNonterminals::getNullableNonterminals);
+auto NullableNonterminalsLeftLG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::LeftLG>(NullableNonterminals::getInstance(), NullableNonterminals::getNullableNonterminals);
+auto NullableNonterminalsLeftRG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::LeftRG>(NullableNonterminals::getInstance(), NullableNonterminals::getNullableNonterminals);
+auto NullableNonterminalsRightLG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightLG>(NullableNonterminals::getInstance(), NullableNonterminals::getNullableNonterminals);
+auto NullableNonterminalsRightRG = NullableNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightRG>(NullableNonterminals::getInstance(), NullableNonterminals::getNullableNonterminals);
 
 std::set<alphabet::Symbol> NullableNonterminals::getNullableNonterminals(const grammar::Grammar& grammar) {
-	std::set<alphabet::Symbol> out;
-	grammar.getData().Accept((void*) &out, NullableNonterminals::NULLABLE_NONTERMINALS);
-	return out;
+	return getInstance().dispatch(grammar.getData());
 }
 
-void NullableNonterminals::Visit(void* data, const grammar::LeftLG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getNullableNonterminals(grammar));
-}
-
-void NullableNonterminals::Visit(void* data, const grammar::LeftRG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getNullableNonterminals(grammar));
-}
-
-void NullableNonterminals::Visit(void* data, const grammar::RightLG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getNullableNonterminals(grammar));
-}
-
-void NullableNonterminals::Visit(void* data, const grammar::RightRG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getNullableNonterminals(grammar));
-}
-
-void NullableNonterminals::Visit(void* data, const grammar::LG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getNullableNonterminals(grammar));
-}
-
-void NullableNonterminals::Visit(void* data, const grammar::CFG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getNullableNonterminals(grammar));
-}
-
-void NullableNonterminals::Visit(void* data, const grammar::EpsilonFreeCFG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getNullableNonterminals(grammar));
-}
-
-void NullableNonterminals::Visit(void* data, const grammar::CNF& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getNullableNonterminals(grammar));
-}
-
-void NullableNonterminals::Visit(void* data, const grammar::GNF& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getNullableNonterminals(grammar));
-}
-
-void NullableNonterminals::Visit(void*, const grammar::CSG&) const {
-	throw exception::AlibException("Unsupported grammar type CSG");
-}
-
-void NullableNonterminals::Visit(void*, const grammar::NonContractingGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type NonConctractingGrammar");
-}
-
-void NullableNonterminals::Visit(void*, const grammar::ContextPreservingUnrestrictedGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type ContextPreservingUnrestrictedGrammar");
-}
-
-void NullableNonterminals::Visit(void*, const grammar::UnrestrictedGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type UnrestrictedGrammar");
-}
-
-const NullableNonterminals NullableNonterminals::NULLABLE_NONTERMINALS;
-
 } /* namespace properties */
 
 } /* namespace grammar */
diff --git a/alib2algo/src/grammar/properties/NullableNonterminals.h b/alib2algo/src/grammar/properties/NullableNonterminals.h
index 85e47beb54..dc67ac96b5 100644
--- a/alib2algo/src/grammar/properties/NullableNonterminals.h
+++ b/alib2algo/src/grammar/properties/NullableNonterminals.h
@@ -8,6 +8,8 @@
 #ifndef NULLABLE_NONTERMINALS_H_
 #define NULLABLE_NONTERMINALS_H_
 
+#include <common/multipleDispatch.hpp>
+
 #include <grammar/Grammar.h>
 #include <alphabet/Symbol.h>
 
@@ -18,10 +20,8 @@ namespace properties {
 /**
  * Implements algorithms from Melichar, chapter 3.3
  */
-class NullableNonterminals : public grammar::VisitableGrammarBase::const_visitor_type {
+class NullableNonterminals : public std::SingleDispatch<std::set<alphabet::Symbol>, grammar::GrammarBase> {
 public:
-	NullableNonterminals() {}
-
 	static std::set<alphabet::Symbol> getNullableNonterminals( const grammar::Grammar & grammar );
 
 	/**
@@ -36,22 +36,10 @@ public:
 	template<class T>
 	static std::set<alphabet::Symbol> getNullableNonterminals(const T& grammar);
 
-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 NullableNonterminals NULLABLE_NONTERMINALS;
+	static NullableNonterminals& getInstance() {
+		static NullableNonterminals res;
+		return res;
+	}
 };
 
 } /* namespace properties */
diff --git a/alib2algo/src/grammar/properties/ProductiveNonterminals.cpp b/alib2algo/src/grammar/properties/ProductiveNonterminals.cpp
index 6b6757ce3a..e32f023dc1 100644
--- a/alib2algo/src/grammar/properties/ProductiveNonterminals.cpp
+++ b/alib2algo/src/grammar/properties/ProductiveNonterminals.cpp
@@ -56,85 +56,20 @@ std::set<alphabet::Symbol> ProductiveNonterminals::getProductiveNonterminals( co
 	return Ni.at( i );
 }
 
-template std::set<alphabet::Symbol> ProductiveNonterminals::getProductiveNonterminals( const grammar::CFG & grammar );
-template std::set<alphabet::Symbol> ProductiveNonterminals::getProductiveNonterminals( const grammar::EpsilonFreeCFG & grammar );
-template std::set<alphabet::Symbol> ProductiveNonterminals::getProductiveNonterminals( const grammar::GNF & grammar );
-template std::set<alphabet::Symbol> ProductiveNonterminals::getProductiveNonterminals( const grammar::CNF & grammar );
-template std::set<alphabet::Symbol> ProductiveNonterminals::getProductiveNonterminals( const grammar::LG & grammar );
-template std::set<alphabet::Symbol> ProductiveNonterminals::getProductiveNonterminals( const grammar::LeftLG & grammar );
-template std::set<alphabet::Symbol> ProductiveNonterminals::getProductiveNonterminals( const grammar::LeftRG & grammar );
-template std::set<alphabet::Symbol> ProductiveNonterminals::getProductiveNonterminals( const grammar::RightLG & grammar );
-template std::set<alphabet::Symbol> ProductiveNonterminals::getProductiveNonterminals( const grammar::RightRG & grammar );
+auto ProductiveNonterminalsCFG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CFG>(ProductiveNonterminals::getInstance(), ProductiveNonterminals::getProductiveNonterminals);
+auto ProductiveNonterminalsEpsilonFreeCFG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG>(ProductiveNonterminals::getInstance(), ProductiveNonterminals::getProductiveNonterminals);
+auto ProductiveNonterminalsGNF = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF>(ProductiveNonterminals::getInstance(), ProductiveNonterminals::getProductiveNonterminals);
+auto ProductiveNonterminalsCNF = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CNF>(ProductiveNonterminals::getInstance(), ProductiveNonterminals::getProductiveNonterminals);
+auto ProductiveNonterminalsLG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::LG>(ProductiveNonterminals::getInstance(), ProductiveNonterminals::getProductiveNonterminals);
+auto ProductiveNonterminalsLeftLG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::LeftLG>(ProductiveNonterminals::getInstance(), ProductiveNonterminals::getProductiveNonterminals);
+auto ProductiveNonterminalsLeftRG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::LeftRG>(ProductiveNonterminals::getInstance(), ProductiveNonterminals::getProductiveNonterminals);
+auto ProductiveNonterminalsRightLG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightLG>(ProductiveNonterminals::getInstance(), ProductiveNonterminals::getProductiveNonterminals);
+auto ProductiveNonterminalsRightRG = ProductiveNonterminals::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightRG>(ProductiveNonterminals::getInstance(), ProductiveNonterminals::getProductiveNonterminals);
 
 std::set<alphabet::Symbol> ProductiveNonterminals::getProductiveNonterminals(const grammar::Grammar& grammar) {
-	std::set<alphabet::Symbol> out;
-	grammar.getData().Accept((void*) &out, ProductiveNonterminals::PRODUCTIVE_NONTERMINALS);
-	return out;
+	return getInstance().dispatch(grammar.getData());
 }
 
-void ProductiveNonterminals::Visit(void* data, const grammar::LeftLG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getProductiveNonterminals(grammar));
-}
-
-void ProductiveNonterminals::Visit(void* data, const grammar::LeftRG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getProductiveNonterminals(grammar));
-}
-
-void ProductiveNonterminals::Visit(void* data, const grammar::RightLG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getProductiveNonterminals(grammar));
-}
-
-void ProductiveNonterminals::Visit(void* data, const grammar::RightRG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getProductiveNonterminals(grammar));
-}
-
-void ProductiveNonterminals::Visit(void* data, const grammar::LG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getProductiveNonterminals(grammar));
-}
-
-void ProductiveNonterminals::Visit(void* data, const grammar::CFG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getProductiveNonterminals(grammar));
-}
-
-void ProductiveNonterminals::Visit(void* data, const grammar::EpsilonFreeCFG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getProductiveNonterminals(grammar));
-}
-
-void ProductiveNonterminals::Visit(void* data, const grammar::CNF& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getProductiveNonterminals(grammar));
-}
-
-void ProductiveNonterminals::Visit(void* data, const grammar::GNF& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getProductiveNonterminals(grammar));
-}
-
-void ProductiveNonterminals::Visit(void*, const grammar::CSG&) const {
-	throw exception::AlibException("Unsupported grammar type CSG");
-}
-
-void ProductiveNonterminals::Visit(void*, const grammar::NonContractingGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type NonConctractingGrammar");
-}
-
-void ProductiveNonterminals::Visit(void*, const grammar::ContextPreservingUnrestrictedGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type ContextPreservingUnrestrictedGrammar");
-}
-
-void ProductiveNonterminals::Visit(void*, const grammar::UnrestrictedGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type UnrestrictedGrammar");
-}
-
-const ProductiveNonterminals ProductiveNonterminals::PRODUCTIVE_NONTERMINALS;
-
 } /* namespace properties */
 
 } /* namespace grammar */
diff --git a/alib2algo/src/grammar/properties/ProductiveNonterminals.h b/alib2algo/src/grammar/properties/ProductiveNonterminals.h
index 688c011f06..0b88d4144d 100644
--- a/alib2algo/src/grammar/properties/ProductiveNonterminals.h
+++ b/alib2algo/src/grammar/properties/ProductiveNonterminals.h
@@ -8,6 +8,8 @@
 #ifndef PRODUCTIVE_NONTERMINALS_H_
 #define PRODUCTIVE_NONTERMINALS_H_
 
+#include <common/multipleDispatch.hpp>
+
 #include <grammar/Grammar.h>
 #include <alphabet/Symbol.h>
 
@@ -18,10 +20,8 @@ namespace properties {
 /**
  * Implements algorithms from Melichar, chapter 3.3
  */
-class ProductiveNonterminals : public grammar::VisitableGrammarBase::const_visitor_type {
+class ProductiveNonterminals : public std::SingleDispatch<std::set<alphabet::Symbol>, grammar::GrammarBase> {
 public:
-	ProductiveNonterminals() {}
-
 	static std::set<alphabet::Symbol> getProductiveNonterminals( const grammar::Grammar & grammar );
 
 	/**
@@ -30,22 +30,10 @@ public:
 	template<class T>
 	static std::set<alphabet::Symbol> getProductiveNonterminals( const T & grammar );
 
-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 ProductiveNonterminals PRODUCTIVE_NONTERMINALS;
+	static ProductiveNonterminals& getInstance() {
+		static ProductiveNonterminals res;
+		return res;
+	}
 };
 
 } /* namespace properties */
diff --git a/alib2algo/src/grammar/properties/UnreachableSymbols.cpp b/alib2algo/src/grammar/properties/UnreachableSymbols.cpp
index 3c0d9bfd63..3f83b5dd7f 100644
--- a/alib2algo/src/grammar/properties/UnreachableSymbols.cpp
+++ b/alib2algo/src/grammar/properties/UnreachableSymbols.cpp
@@ -57,85 +57,20 @@ std::set<alphabet::Symbol> UnreachableSymbols::getUnreachableSymbols( const T &
 	return Vi.at( i );
 }
 
-template std::set<alphabet::Symbol> UnreachableSymbols::getUnreachableSymbols( const grammar::CFG & grammar );
-template std::set<alphabet::Symbol> UnreachableSymbols::getUnreachableSymbols( const grammar::EpsilonFreeCFG & grammar );
-template std::set<alphabet::Symbol> UnreachableSymbols::getUnreachableSymbols( const grammar::GNF & grammar );
-template std::set<alphabet::Symbol> UnreachableSymbols::getUnreachableSymbols( const grammar::CNF & grammar );
-template std::set<alphabet::Symbol> UnreachableSymbols::getUnreachableSymbols( const grammar::LG & grammar );
-template std::set<alphabet::Symbol> UnreachableSymbols::getUnreachableSymbols( const grammar::LeftLG & grammar );
-template std::set<alphabet::Symbol> UnreachableSymbols::getUnreachableSymbols( const grammar::LeftRG & grammar );
-template std::set<alphabet::Symbol> UnreachableSymbols::getUnreachableSymbols( const grammar::RightLG & grammar );
-template std::set<alphabet::Symbol> UnreachableSymbols::getUnreachableSymbols( const grammar::RightRG & grammar );
+auto UnreachableSymbolsCFG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CFG>(UnreachableSymbols::getInstance(), UnreachableSymbols::getUnreachableSymbols);
+auto UnreachableSymbolsEpsilonFreeCFG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::EpsilonFreeCFG>(UnreachableSymbols::getInstance(), UnreachableSymbols::getUnreachableSymbols);
+auto UnreachableSymbolsGNF = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::GNF>(UnreachableSymbols::getInstance(), UnreachableSymbols::getUnreachableSymbols);
+auto UnreachableSymbolsCNF = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::CNF>(UnreachableSymbols::getInstance(), UnreachableSymbols::getUnreachableSymbols);
+auto UnreachableSymbolsLG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::LG>(UnreachableSymbols::getInstance(), UnreachableSymbols::getUnreachableSymbols);
+auto UnreachableSymbolsLeftLG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::LeftLG>(UnreachableSymbols::getInstance(), UnreachableSymbols::getUnreachableSymbols);
+auto UnreachableSymbolsLeftRG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::LeftRG>(UnreachableSymbols::getInstance(), UnreachableSymbols::getUnreachableSymbols);
+auto UnreachableSymbolsRightLG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightLG>(UnreachableSymbols::getInstance(), UnreachableSymbols::getUnreachableSymbols);
+auto UnreachableSymbolsRightRG = UnreachableSymbols::RegistratorWrapper<std::set<alphabet::Symbol>, grammar::RightRG>(UnreachableSymbols::getInstance(), UnreachableSymbols::getUnreachableSymbols);
 
 std::set<alphabet::Symbol> UnreachableSymbols::getUnreachableSymbols(const grammar::Grammar& grammar) {
-	std::set<alphabet::Symbol> out;
-	grammar.getData().Accept((void*) &out, UnreachableSymbols::UNREACHABLE_NONTERMINALS);
-	return out;
+	return getInstance().dispatch(grammar.getData());
 }
 
-void UnreachableSymbols::Visit(void* data, const grammar::LeftLG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getUnreachableSymbols(grammar));
-}
-
-void UnreachableSymbols::Visit(void* data, const grammar::LeftRG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getUnreachableSymbols(grammar));
-}
-
-void UnreachableSymbols::Visit(void* data, const grammar::RightLG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getUnreachableSymbols(grammar));
-}
-
-void UnreachableSymbols::Visit(void* data, const grammar::RightRG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getUnreachableSymbols(grammar));
-}
-
-void UnreachableSymbols::Visit(void* data, const grammar::LG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getUnreachableSymbols(grammar));
-}
-
-void UnreachableSymbols::Visit(void* data, const grammar::CFG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getUnreachableSymbols(grammar));
-}
-
-void UnreachableSymbols::Visit(void* data, const grammar::EpsilonFreeCFG& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getUnreachableSymbols(grammar));
-}
-
-void UnreachableSymbols::Visit(void* data, const grammar::CNF& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getUnreachableSymbols(grammar));
-}
-
-void UnreachableSymbols::Visit(void* data, const grammar::GNF& grammar) const {
-	std::set<alphabet::Symbol> & out = *((std::set<alphabet::Symbol>*) data);
-	out = std::move(this->getUnreachableSymbols(grammar));
-}
-
-void UnreachableSymbols::Visit(void*, const grammar::CSG&) const {
-	throw exception::AlibException("Unsupported grammar type CSG");
-}
-
-void UnreachableSymbols::Visit(void*, const grammar::NonContractingGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type NonConctractingGrammar");
-}
-
-void UnreachableSymbols::Visit(void*, const grammar::ContextPreservingUnrestrictedGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type ContextPreservingUnrestrictedGrammar");
-}
-
-void UnreachableSymbols::Visit(void*, const grammar::UnrestrictedGrammar&) const {
-	throw exception::AlibException("Unsupported grammar type UnrestrictedGrammar");
-}
-
-const UnreachableSymbols UnreachableSymbols::UNREACHABLE_NONTERMINALS;
-
 } /* namespace properties */
 
 } /* namespace grammar */
diff --git a/alib2algo/src/grammar/properties/UnreachableSymbols.h b/alib2algo/src/grammar/properties/UnreachableSymbols.h
index a77f3421e2..c25efea009 100644
--- a/alib2algo/src/grammar/properties/UnreachableSymbols.h
+++ b/alib2algo/src/grammar/properties/UnreachableSymbols.h
@@ -8,6 +8,8 @@
 #ifndef UNREACHABLE_SYMBOLS_H_
 #define UNREACHABLE_SYMBOLS_H_
 
+#include <common/multipleDispatch.hpp>
+
 #include <grammar/Grammar.h>
 #include <alphabet/Symbol.h>
 
@@ -18,10 +20,8 @@ namespace properties {
 /**
  * Implements algorithms from Melichar, chapter 3.3
  */
-class UnreachableSymbols : public grammar::VisitableGrammarBase::const_visitor_type {
+class UnreachableSymbols : public std::SingleDispatch<std::set<alphabet::Symbol>, grammar::GrammarBase> {
 public:
-	UnreachableSymbols() {}
-
 	static std::set<alphabet::Symbol> getUnreachableSymbols( const grammar::Grammar & grammar );
 
 	/**
@@ -30,22 +30,10 @@ public:
 	template<class T>
 	static std::set<alphabet::Symbol> getUnreachableSymbols( const T & grammar );
 
-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 UnreachableSymbols UNREACHABLE_NONTERMINALS;
+	static UnreachableSymbols& getInstance() {
+		static UnreachableSymbols res;
+		return res;
+	}
 };
 
 } /* namespace properties */
diff --git a/alib2algo/src/regexp/properties/RegExpEpsilon.h b/alib2algo/src/regexp/properties/RegExpEpsilon.h
index 887a42c16b..f0cdaaf094 100644
--- a/alib2algo/src/regexp/properties/RegExpEpsilon.h
+++ b/alib2algo/src/regexp/properties/RegExpEpsilon.h
@@ -22,8 +22,7 @@ namespace properties {
  * Checks, whether regexp (or its subtree) describes epsilon (empty string).
  *
  */
-class RegExpEpsilon : public std::SingleDispatch<bool, regexp::RegExpBase>, regexp::FormalRegExpElement::const_visitor_type, regexp::UnboundedRegExpElement::const_visitor_type
-{
+class RegExpEpsilon : public std::SingleDispatch<bool, regexp::RegExpBase>, regexp::FormalRegExpElement::const_visitor_type, regexp::UnboundedRegExpElement::const_visitor_type {
 public:
 	RegExpEpsilon() {}
 
-- 
GitLab