diff --git a/alib2algo/src/graph/shortestpath/BellmanFord.cpp b/alib2algo/src/graph/shortestpath/BellmanFord.cpp
index 85c3f35fc797ca656e78852f6b7382742aa7f1b3..3e8c37be7054d68ac3538b9739dead0e3b686c75 100644
--- a/alib2algo/src/graph/shortestpath/BellmanFord.cpp
+++ b/alib2algo/src/graph/shortestpath/BellmanFord.cpp
@@ -104,9 +104,7 @@ static BellmanFord::Result bellmanford_impl(const UndirectedGraph &graph, const
 
 BellmanFord::Result BellmanFord::bellmanford(const Graph &graph, const Node &start)
 {
-	Data data = {start, BellmanFord::Result {}};
-	graph.getData().Accept(static_cast<void*>(&data), BELLMAN_FORD);
-	return data.out;
+	return getInstance().dispatch(graph.getData(), start);
 }
 
 BellmanFord::Result BellmanFord::bellmanford(const DirectedGraph &graph, const Node &start)
@@ -114,24 +112,14 @@ BellmanFord::Result BellmanFord::bellmanford(const DirectedGraph &graph, const N
 	return bellmanford_impl(graph, start);
 }
 
+auto BellmanFordDirectedGraph = BellmanFord::RegistratorWrapper<BellmanFord::Result, graph::DirectedGraph>(BellmanFord::getInstance(), BellmanFord::bellmanford);
+
 BellmanFord::Result BellmanFord::bellmanford(const UndirectedGraph &graph, const Node &start)
 {
 	return bellmanford_impl(graph, start);
 }
 
-void BellmanFord::Visit(void *data, const DirectedGraph &graph) const
-{
-	Data d = *static_cast<Data*>(data);
-	d.out = bellmanford(graph, d.start);
-}
-
-void BellmanFord::Visit(void *data, const UndirectedGraph &graph) const
-{
-	Data d = *static_cast<Data*>(data);
-	d.out = bellmanford(graph, d.start);
-}
-
-const BellmanFord BellmanFord::BELLMAN_FORD;
+auto BellmanFordUndirectedGraph = BellmanFord::RegistratorWrapper<BellmanFord::Result, graph::UndirectedGraph>(BellmanFord::getInstance(), BellmanFord::bellmanford);
 
 } // namespace shortestpath
 
diff --git a/alib2algo/src/graph/shortestpath/BellmanFord.h b/alib2algo/src/graph/shortestpath/BellmanFord.h
index 730175966d90b4b39eae277514898ab3dfd7bf93..9c5a07e2dd8d6a889b8b9f1e1cc0fef6b045b6b2 100644
--- a/alib2algo/src/graph/shortestpath/BellmanFord.h
+++ b/alib2algo/src/graph/shortestpath/BellmanFord.h
@@ -1,28 +1,24 @@
 #ifndef GRAPH_BELLMAN_FORD_H_
 #define GRAPH_BELLMAN_FORD_H_
 
+#include <common/multipleDispatch.hpp>
 #include <unordered_map>
 
 #include <graph/Graph.h>
 #include <graph/directed/DirectedGraph.h>
 #include <graph/undirected/UndirectedGraph.h>
 
-namespace graph
-{
+namespace graph {
 
-namespace shortestpath
-{
+namespace shortestpath {
 
 // Bellman-Ford only works on graphs without negative-weight cycle
 // However it will detect the negative-weight cycle and throw exception
 //
 // note: negative-weight undirected edge = negative-weight cycle
 
-class BellmanFord : public graph::VisitableGraphBase::const_visitor_type
-{
+class BellmanFord : public std::SingleDispatchLastStaticParam<std::unordered_map<Node, int>, graph::GraphBase, const Node> {
 public:
-	BellmanFord() {}
-
 	typedef std::unordered_map<Node, int> Result;
 
 	static Result bellmanford(const Graph &graph, const Node &start);
@@ -30,11 +26,10 @@ public:
 	static Result bellmanford(const DirectedGraph &graph, const Node &start);
 	static Result bellmanford(const UndirectedGraph &graph, const Node &start);
 
-private:
-	void Visit(void *data, const DirectedGraph &graph) const;
-	void Visit(void *data, const UndirectedGraph &graph) const;
-
-	static const BellmanFord BELLMAN_FORD;
+	static BellmanFord& getInstance() {
+		static BellmanFord res;
+		return res;
+	}
 };
 
 } // namespace shortestpath
diff --git a/alib2algo/src/graph/shortestpath/Dijkstra.cpp b/alib2algo/src/graph/shortestpath/Dijkstra.cpp
index bb1ef7dc86737cb945b4a859186f8013f16fc25e..e4f59b4632d259a6a12146d2d928267b3fb90b90 100644
--- a/alib2algo/src/graph/shortestpath/Dijkstra.cpp
+++ b/alib2algo/src/graph/shortestpath/Dijkstra.cpp
@@ -120,9 +120,7 @@ static Dijkstra::Result dijkstra_impl(const T &graph, const Node &start)
 
 Dijkstra::Result Dijkstra::dijkstra(const Graph &graph, const Node &start)
 {
-	Data data = {start, Dijkstra::Result {}};
-	graph.getData().Accept(static_cast<void*>(&data), DIJKSTRA);
-	return data.out;
+	return getInstance().dispatch(graph.getData(), start);
 }
 
 Dijkstra::Result Dijkstra::dijkstra(const DirectedGraph &graph, const Node &start)
@@ -130,24 +128,14 @@ Dijkstra::Result Dijkstra::dijkstra(const DirectedGraph &graph, const Node &star
 	return dijkstra_impl(graph, start);
 }
 
+auto DijkstraDirectedGraph = Dijkstra::RegistratorWrapper<Dijkstra::Result, graph::DirectedGraph>(Dijkstra::getInstance(), Dijkstra::dijkstra);
+
 Dijkstra::Result Dijkstra::dijkstra(const UndirectedGraph &graph, const Node &start)
 {
 	return dijkstra_impl(graph, start);
 }
 
-void Dijkstra::Visit(void *data, const DirectedGraph &graph) const
-{
-	Data d = *static_cast<Data*>(data);
-	d.out = dijkstra(graph, d.start);
-}
-
-void Dijkstra::Visit(void *data, const UndirectedGraph &graph) const
-{
-	Data d = *static_cast<Data*>(data);
-	d.out = dijkstra(graph, d.start);
-}
-
-const Dijkstra Dijkstra::DIJKSTRA;
+auto DijkstraUndirectedGraph = Dijkstra::RegistratorWrapper<Dijkstra::Result, graph::UndirectedGraph>(Dijkstra::getInstance(), Dijkstra::dijkstra);
 
 } // namespace shortestpath
 
diff --git a/alib2algo/src/graph/shortestpath/Dijkstra.h b/alib2algo/src/graph/shortestpath/Dijkstra.h
index 52cf36902b1945420a6160b60bce1ecb57a6f020..d1fc6af8c6ce9f6fe904141bf02e7c2b94bc4beb 100644
--- a/alib2algo/src/graph/shortestpath/Dijkstra.h
+++ b/alib2algo/src/graph/shortestpath/Dijkstra.h
@@ -1,25 +1,21 @@
 #ifndef GRAPH_DIJKSTRA_H_
 #define GRAPH_DIJKSTRA_H_
 
+#include <common/multipleDispatch.hpp>
 #include <unordered_map>
 
 #include <graph/Graph.h>
 #include <graph/directed/DirectedGraph.h>
 #include <graph/undirected/UndirectedGraph.h>
 
-namespace graph
-{
+namespace graph {
 
-namespace shortestpath
-{
+namespace shortestpath {
 
 // Dijkstra only works on graphs without negative-weight edges (>= 0)
 
-class Dijkstra : public graph::VisitableGraphBase::const_visitor_type
-{
+class Dijkstra : public std::SingleDispatchLastStaticParam<std::unordered_map<Node, int>, graph::GraphBase, const Node> {
 public:
-	Dijkstra() {}
-
 	typedef std::unordered_map<Node, int> Result;
 
 	static Result dijkstra(const Graph &graph, const Node &start);
@@ -27,11 +23,10 @@ public:
 	static Result dijkstra(const DirectedGraph &graph, const Node &start);
 	static Result dijkstra(const UndirectedGraph &graph, const Node &start);
 
-private:
-	void Visit(void *data, const DirectedGraph &graph) const;
-	void Visit(void *data, const UndirectedGraph &graph) const;
-
-	static const Dijkstra DIJKSTRA;
+	static Dijkstra& getInstance() {
+		static Dijkstra res;
+		return res;
+	}
 };
 
 } // namespace shortestpath
diff --git a/alib2algo/src/graph/shortestpath/FloydWarshall.cpp b/alib2algo/src/graph/shortestpath/FloydWarshall.cpp
index ec9a40bef55708cc73890ce3a0c4fb3cc13cfb1f..4cd4df7da223f694f33613ee263d70e147a96377 100644
--- a/alib2algo/src/graph/shortestpath/FloydWarshall.cpp
+++ b/alib2algo/src/graph/shortestpath/FloydWarshall.cpp
@@ -59,9 +59,7 @@ static FloydWarshall::Result floydwarshall_impl(const T &graph)
 
 FloydWarshall::Result FloydWarshall::floydwarshall(const Graph &graph)
 {
-	Result res;
-	graph.getData().Accept(static_cast<void*>(&res), FLOYD_WARSHALL);
-	return res;
+	return getInstance().dispatch(graph.getData());
 }
 
 FloydWarshall::Result FloydWarshall::floydwarshall(const DirectedGraph &graph)
@@ -69,24 +67,14 @@ FloydWarshall::Result FloydWarshall::floydwarshall(const DirectedGraph &graph)
 	return floydwarshall_impl(graph);
 }
 
+auto FloydWarshallDirectedGraph = FloydWarshall::RegistratorWrapper<FloydWarshall::Result, graph::DirectedGraph>(FloydWarshall::getInstance(), FloydWarshall::floydwarshall);
+
 FloydWarshall::Result FloydWarshall::floydwarshall(const UndirectedGraph &graph)
 {
 	return floydwarshall_impl(graph);
 }
 
-void FloydWarshall::Visit(void *data, const DirectedGraph &graph) const
-{
-	Result *r = static_cast<Result*>(data);
-	*r = floydwarshall(graph);
-}
-
-void FloydWarshall::Visit(void *data, const UndirectedGraph &graph) const
-{
-	Result *r = static_cast<Result*>(data);
-	*r = floydwarshall(graph);
-}
-
-const FloydWarshall FloydWarshall::FLOYD_WARSHALL;
+auto FloydWarshallUndirectedGraph = FloydWarshall::RegistratorWrapper<FloydWarshall::Result, graph::UndirectedGraph>(FloydWarshall::getInstance(), FloydWarshall::floydwarshall);
 
 } // namespace shortestpath
 
diff --git a/alib2algo/src/graph/shortestpath/FloydWarshall.h b/alib2algo/src/graph/shortestpath/FloydWarshall.h
index bbc16ca70802693ef9d4165de691eef55dcd1b4b..367d62016fca34f7a4313505ae8dc5e64c5c2493 100644
--- a/alib2algo/src/graph/shortestpath/FloydWarshall.h
+++ b/alib2algo/src/graph/shortestpath/FloydWarshall.h
@@ -1,17 +1,16 @@
 #ifndef GRAPH_FLOYD_WARSHALL_FORD_H_
 #define GRAPH_FLOYD_WARSHALL_FORD_H_
 
+#include <common/multipleDispatch.hpp>
 #include <unordered_map>
 
 #include <graph/Graph.h>
 #include <graph/directed/DirectedGraph.h>
 #include <graph/undirected/UndirectedGraph.h>
 
-namespace graph
-{
+namespace graph {
 
-namespace shortestpath
-{
+namespace shortestpath {
 
 // Floyd-Warshall only works on graphs without negative-weight cycle
 // However it will detect the negative-weight cycle and throw exception
@@ -19,11 +18,8 @@ namespace shortestpath
 // note: negative-weight undirected edge = negative-weight cycle
 // note: std::numeric_limits<int>::max() is used as infinity
 
-class FloydWarshall : public graph::VisitableGraphBase::const_visitor_type
-{
+class FloydWarshall : public std::SingleDispatch<std::unordered_map<Node, std::unordered_map<Node, int>>, graph::GraphBase> {
 public:
-	FloydWarshall() {}
-
 	typedef std::unordered_map<Node, std::unordered_map<Node, int>> Result;
 
 	static Result floydwarshall(const Graph &graph);
@@ -31,11 +27,10 @@ public:
 	static Result floydwarshall(const DirectedGraph &graph);
 	static Result floydwarshall(const UndirectedGraph &graph);
 
-private:
-	void Visit(void *data, const DirectedGraph &graph) const;
-	void Visit(void *data, const UndirectedGraph &graph) const;
-
-	static const FloydWarshall FLOYD_WARSHALL;
+	static FloydWarshall& getInstance() {
+		static FloydWarshall res;
+		return res;
+	}
 };
 
 } // namespace shortestpath
diff --git a/alib2algo/src/graph/sort/TopologicalSort.cpp b/alib2algo/src/graph/sort/TopologicalSort.cpp
index 6556074b1c0d1274823f433e917749df83ea56ba..3ecbeadbd790910579da6748dffb7b924be35cc9 100644
--- a/alib2algo/src/graph/sort/TopologicalSort.cpp
+++ b/alib2algo/src/graph/sort/TopologicalSort.cpp
@@ -3,14 +3,11 @@
 
 #include <exception/AlibException.h>
 
-namespace graph
-{
+namespace graph {
 
-namespace sort
-{
+namespace sort {
 
-static TopologicalSort::Result topsort_impl(const DirectedGraph &graph)
-{
+static TopologicalSort::Result topsort_impl(const DirectedGraph &graph) {
 	TopologicalSort::Result s;
 	std::unordered_map<Node, bool> visited;
 
@@ -28,32 +25,15 @@ static TopologicalSort::Result topsort_impl(const DirectedGraph &graph)
 	return s;
 }
 
-TopologicalSort::Result TopologicalSort::topologicalsort(const Graph &graph)
-{
-	Result res;
-	graph.getData().Accept(static_cast<void*>(&res), TOPOLOGICAL_SORT);
-	return res;
+TopologicalSort::Result TopologicalSort::topologicalsort(const Graph &graph) {
+	return getInstance().dispatch(graph.getData());
 }
 
-TopologicalSort::Result TopologicalSort::topologicalsort(const DirectedGraph &graph)
-{
+TopologicalSort::Result TopologicalSort::topologicalsort(const DirectedGraph &graph) {
 	return topsort_impl(graph);
 }
 
-void TopologicalSort::Visit(void *data, const DirectedGraph &graph) const
-{
-	Result *r = static_cast<Result*>(data);
-	*r = topologicalsort(graph);
-}
-
-void TopologicalSort::Visit(void *data, const UndirectedGraph &graph) const
-{
-	(void) data;
-	(void) graph;
-	throw exception::AlibException("Unsupported graph type UndirectedGraph");
-}
-
-const TopologicalSort TopologicalSort::TOPOLOGICAL_SORT;
+auto TopologicalSortDirectedGraph = TopologicalSort::RegistratorWrapper<TopologicalSort::Result, graph::DirectedGraph>(TopologicalSort::getInstance(), TopologicalSort::topologicalsort);
 
 } // namespace sort
 
diff --git a/alib2algo/src/graph/sort/TopologicalSort.h b/alib2algo/src/graph/sort/TopologicalSort.h
index b746cb2bd5f12d6ff0e53cd0a8a8758e062df8db..e43fbd0d60c8071223b92a9fe45618f7f4ab7e97 100644
--- a/alib2algo/src/graph/sort/TopologicalSort.h
+++ b/alib2algo/src/graph/sort/TopologicalSort.h
@@ -1,34 +1,29 @@
 #ifndef GRAPH_TOPOLOGICAL_SORT_H_
 #define GRAPH_TOPOLOGICAL_SORT_H_
 
+#include <common/multipleDispatch.hpp>
 #include <list>
 
 #include <graph/Graph.h>
 #include <graph/directed/DirectedGraph.h>
 #include <graph/undirected/UndirectedGraph.h>
 
-namespace graph
-{
+namespace graph {
 
-namespace sort
-{
+namespace sort {
 
-class TopologicalSort : public graph::VisitableGraphBase::const_visitor_type
-{
+class TopologicalSort : public std::SingleDispatch<std::list<Node>, graph::GraphBase> {
 public:
-	TopologicalSort() {}
-
 	typedef std::list<Node> Result;
 
 	static Result topologicalsort(const Graph &graph);
 
 	static Result topologicalsort(const DirectedGraph &graph);
 
-private:
-	void Visit(void *data, const DirectedGraph &graph) const;
-	void Visit(void *data, const UndirectedGraph &graph) const;
-
-	static const TopologicalSort TOPOLOGICAL_SORT;
+	static TopologicalSort& getInstance() {
+		static TopologicalSort res;
+		return res;
+	}
 };
 
 } // namespace sort
diff --git a/alib2algo/src/graph/spanningtree/JarnikPrim.cpp b/alib2algo/src/graph/spanningtree/JarnikPrim.cpp
index 28f55bfbbe5c6b13763ba5ea54762ef02b02df59..5222d2a374db648ed6b09a10fde120cd501d1251 100644
--- a/alib2algo/src/graph/spanningtree/JarnikPrim.cpp
+++ b/alib2algo/src/graph/spanningtree/JarnikPrim.cpp
@@ -4,21 +4,17 @@
 
 #include <limits>
 
-namespace graph
-{
+namespace graph {
 
-namespace spanningtree
-{
+namespace spanningtree {
 
-class Data
-{
+class Data {
 public:
 	Node start;
 	Graph *out;
 };
 
-class Value
-{
+class Value {
 public:
 	Value(const Node &node, int value)
 		: node(node)
@@ -40,8 +36,7 @@ public:
 
 typedef std::unordered_map<Node, std::unordered_map<Node, int>> weights_t;
 
-static weights_t weights(const UndirectedGraph &g)
-{
+static weights_t weights(const UndirectedGraph &g) {
 	int val;
 	weights_t w;
 
@@ -63,8 +58,7 @@ static weights_t weights(const UndirectedGraph &g)
 	return w;
 }
 
-static UndirectedGraph jarnikprim_impl(const UndirectedGraph &graph, const Node &start)
-{
+static UndirectedGraph jarnikprim_impl(const UndirectedGraph &graph, const Node &start) {
 	UndirectedGraph res;              // spanning tree
 	std::set<Value> q;                // priority queue
 	weights_t w = weights(graph);     // minimum weights
@@ -101,35 +95,15 @@ static UndirectedGraph jarnikprim_impl(const UndirectedGraph &graph, const Node
 	return res;
 }
 
-Graph JarnikPrim::jarnikprim(const Graph &graph, const Node &start)
-{
-	Data out = { start, nullptr };
-	graph.getData().Accept(static_cast<void*>(&out), JARNIK_PRIM);
-	Graph res = std::move(*out.out);
-	delete out.out;
-	return res;
+Graph JarnikPrim::jarnikprim(const Graph &graph, const Node &start) {
+	return getInstance().dispatch(graph.getData(), start);
 }
 
-UndirectedGraph JarnikPrim::jarnikprim(const UndirectedGraph &graph, const Node &start)
-{
+UndirectedGraph JarnikPrim::jarnikprim(const UndirectedGraph &graph, const Node &start) {
 	return jarnikprim_impl(graph, start);
 }
 
-void JarnikPrim::Visit(void *data, const DirectedGraph &graph) const
-{
-	(void) data;
-	(void) graph;
-	throw exception::AlibException("Unsupported graph type DirectedGraph");
-}
-
-void JarnikPrim::Visit(void *data, const UndirectedGraph &graph) const
-{
-	Data d = *static_cast<Data*>(data);
-	d.out = new Graph(jarnikprim(graph, d.start));
-	(void) d;
-}
-
-const JarnikPrim JarnikPrim::JARNIK_PRIM;
+auto JarnikPrimUndirectedGraph = JarnikPrim::RegistratorWrapper<graph::UndirectedGraph, graph::UndirectedGraph>(JarnikPrim::getInstance(), JarnikPrim::jarnikprim);
 
 } // namespace spanningtree
 
diff --git a/alib2algo/src/graph/spanningtree/JarnikPrim.h b/alib2algo/src/graph/spanningtree/JarnikPrim.h
index 8b8d11e24b7fab00d35d4272c529189ff1b97d1c..05d80541248961547d7e8e6daab7bc938c849687 100644
--- a/alib2algo/src/graph/spanningtree/JarnikPrim.h
+++ b/alib2algo/src/graph/spanningtree/JarnikPrim.h
@@ -1,30 +1,25 @@
 #ifndef GRAPH_JARNIK_PRIM_H_
 #define GRAPH_JARNIK_PRIM_H_
 
+#include <common/multipleDispatch.hpp>
 #include <graph/Graph.h>
 #include <graph/directed/DirectedGraph.h>
 #include <graph/undirected/UndirectedGraph.h>
 
-namespace graph
-{
+namespace graph {
 
-namespace spanningtree
-{
+namespace spanningtree {
 
-class JarnikPrim : public graph::VisitableGraphBase::const_visitor_type
-{
+class JarnikPrim : public std::SingleDispatchLastStaticParam<graph::Graph, graph::GraphBase, const Node> {
 public:
-	JarnikPrim() {}
-
 	static Graph jarnikprim(const Graph &graph, const Node &start);
 
 	static UndirectedGraph jarnikprim(const UndirectedGraph &graph, const Node &start);
 
-private:
-	void Visit(void *data, const DirectedGraph &graph) const;
-	void Visit(void *data, const UndirectedGraph &graph) const;
-
-	static const JarnikPrim JARNIK_PRIM;
+	static JarnikPrim& getInstance() {
+		static JarnikPrim res;
+		return res;
+	}
 };
 
 } // namespace spanningtree
diff --git a/alib2algo/src/graph/traverse/Bfs.cpp b/alib2algo/src/graph/traverse/Bfs.cpp
index 19e60188d13ac79303fea67ff733351b2e0e6ec3..9b79beb56b44cdb954574897ad5bc48cadb72c4b 100644
--- a/alib2algo/src/graph/traverse/Bfs.cpp
+++ b/alib2algo/src/graph/traverse/Bfs.cpp
@@ -3,22 +3,18 @@
 #include <queue>
 #include <unordered_map>
 
-namespace graph
-{
+namespace graph {
 
-namespace traverse
-{
+namespace traverse {
 
-struct Data
-{
+struct Data {
 	Node start;
 	Bfs::Function func;
 	Bfs::FunctionExt func2;
 };
 
 template <typename T>
-static void bfs_impl(const T &graph, const Node &start, Bfs::Function func)
-{
+static void bfs_impl(const T &graph, const Node &start, Bfs::Function func) {
 	std::unordered_map<Node, bool> visited;
 	std::queue<Node> q;
 
@@ -42,8 +38,7 @@ static void bfs_impl(const T &graph, const Node &start, Bfs::Function func)
 }
 
 template <typename T>
-static void bfs2_impl(const T &graph, const Node &start, Bfs::FunctionExt func)
-{
+static void bfs2_impl(const T &graph, const Node &start, Bfs::FunctionExt func) {
 	std::unordered_map<Node, int> distances;
 	std::unordered_map<Node, Node> predecessors;
 	std::queue<Node> q;
@@ -69,59 +64,37 @@ static void bfs2_impl(const T &graph, const Node &start, Bfs::FunctionExt func)
 	}
 }
 
-void Bfs::bfs(const Graph &graph, const Node &start, Bfs::Function func)
-{
-	Data data = { start, func, nullptr };
-	graph.getData().Accept(static_cast<void*>(&data), BFS);
+void Bfs::bfs(const Graph &graph, const Node &start, Bfs::Function func) {
+	getInstance().dispatch(graph.getData(), start, func);
 }
 
-void Bfs::bfs(const Graph &graph, const Node &start, Bfs::FunctionExt func)
-{
-	Data data = { start, nullptr, func };
-	graph.getData().Accept(static_cast<void*>(&data), BFS);
+void Bfs::bfs(const Graph &graph, const Node &start, Bfs::FunctionExt func) {
+	getInstance().dispatch(graph.getData(), start, func);
 }
 
-void Bfs::bfs(const DirectedGraph &graph, const Node &start, Bfs::Function func)
-{
+void Bfs::bfs(const DirectedGraph &graph, const Node &start, Bfs::Function func) {
 	bfs_impl(graph, start, func);
 }
 
-void Bfs::bfs(const DirectedGraph &graph, const Node &start, Bfs::FunctionExt func)
-{
+auto BfsDirectedGraph1 = Bfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Bfs::Function>::RegistratorWrapper<void, graph::DirectedGraph>(Bfs::getInstance(), Bfs::bfs);
+
+void Bfs::bfs(const DirectedGraph &graph, const Node &start, Bfs::FunctionExt func) {
 	bfs2_impl(graph, start, func);
 }
 
-void Bfs::bfs(const UndirectedGraph &graph, const Node &start, Bfs::Function func)
-{
+auto BfsDirectedGraph2 = Bfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Bfs::FunctionExt>::RegistratorWrapper<void, graph::DirectedGraph>(Bfs::getInstance(), Bfs::bfs);
+
+void Bfs::bfs(const UndirectedGraph &graph, const Node &start, Bfs::Function func) {
 	bfs_impl(graph, start, func);
 }
 
-void Bfs::bfs(const UndirectedGraph &graph, const Node &start, Bfs::FunctionExt func)
-{
-	bfs2_impl(graph, start, func);
-}
+auto BfsUndirectedGraph1 = Bfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Bfs::Function>::RegistratorWrapper<void, graph::UndirectedGraph>(Bfs::getInstance(), Bfs::bfs);
 
-void Bfs::Visit(void *data, const DirectedGraph &graph) const
-{
-	Data d = *static_cast<Data*>(data);
-	if (d.func) {
-		bfs(graph, d.start, d.func);
-	} else if (d.func2) {
-		bfs(graph, d.start, d.func2);
-	}
-}
-
-void Bfs::Visit(void *data, const UndirectedGraph &graph) const
-{
-	Data d = *static_cast<Data*>(data);
-	if (d.func) {
-		bfs(graph, d.start, d.func);
-	} else if (d.func2) {
-		bfs(graph, d.start, d.func2);
-	}
+void Bfs::bfs(const UndirectedGraph &graph, const Node &start, Bfs::FunctionExt func) {
+	bfs2_impl(graph, start, func);
 }
 
-const Bfs Bfs::BFS;
+auto BfsUndirectedGraph2 = Bfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Bfs::FunctionExt>::RegistratorWrapper<void, graph::UndirectedGraph>(Bfs::getInstance(), Bfs::bfs);
 
 } // namespace traverse
 
diff --git a/alib2algo/src/graph/traverse/Bfs.h b/alib2algo/src/graph/traverse/Bfs.h
index c180b1a3230dae0d44b7e95788ff64f907755438..2c207d1fee435478e1864ff9cdf7456184769f33 100644
--- a/alib2algo/src/graph/traverse/Bfs.h
+++ b/alib2algo/src/graph/traverse/Bfs.h
@@ -1,25 +1,24 @@
 #ifndef GRAPH_BFS_H_
 #define GRAPH_BFS_H_
 
+#include <common/multipleDispatch.hpp>
 #include <graph/Graph.h>
 #include <graph/directed/DirectedGraph.h>
 #include <graph/undirected/UndirectedGraph.h>
 
-namespace graph
-{
+namespace graph {
 
-namespace traverse
-{
+namespace traverse {
 
 // func is called for each visited node, traversal stops when returning false
 //
 // bool Function(const Node &visitedNode);
 // bool FunctionExt(const Node &visitedNode, const Node &predecessor, int distanceFromStart);
 
-class Bfs : public graph::VisitableGraphBase::const_visitor_type
-{
+class Bfs : public std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&)>>, public std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&, const Node&, int)>> {
 public:
-	Bfs() {}
+	using std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&)>>::dispatch;
+	using std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&, const Node&, int)>>::dispatch;
 
 	typedef std::function<bool(const Node&)> Function;
 	typedef std::function<bool(const Node&, const Node&, int)> FunctionExt;
@@ -32,11 +31,10 @@ public:
 	static void bfs(const UndirectedGraph &graph, const Node &start, Function func);
 	static void bfs(const UndirectedGraph &graph, const Node &start, FunctionExt func);
 
-private:
-	void Visit(void *data, const DirectedGraph &graph) const;
-	void Visit(void *data, const UndirectedGraph &graph) const;
-
-	static const Bfs BFS;
+	static Bfs& getInstance() {
+		static Bfs res;
+		return res;
+	}
 };
 
 } // namespace traverse
diff --git a/alib2algo/src/graph/traverse/Dfs.cpp b/alib2algo/src/graph/traverse/Dfs.cpp
index 2aa7fe3100ddcdc338b98495ffcefd10203ecce4..e49863254e8227e33711591be3c4751e8066c40a 100644
--- a/alib2algo/src/graph/traverse/Dfs.cpp
+++ b/alib2algo/src/graph/traverse/Dfs.cpp
@@ -3,22 +3,18 @@
 #include <stack>
 #include <unordered_map>
 
-namespace graph
-{
+namespace graph {
 
-namespace traverse
-{
+namespace traverse {
 
-struct Data
-{
+struct Data {
 	Node start;
 	Dfs::Function func;
 	Dfs::FunctionExt func2;
 };
 
 template <typename T>
-static void dfs_impl(const T &graph, const Node &start, Dfs::Function func)
-{
+static void dfs_impl(const T &graph, const Node &start, Dfs::Function func) {
 	std::unordered_map<Node, bool> visited;
 	std::stack<Node> s;
 
@@ -42,8 +38,7 @@ static void dfs_impl(const T &graph, const Node &start, Dfs::Function func)
 }
 
 template <typename T>
-static bool dfs2_impl(const T &graph, const Node &n, const Node &p, std::unordered_map<Node, bool> &visited, int &time, Dfs::FunctionExt func)
-{
+static bool dfs2_impl(const T &graph, const Node &n, const Node &p, std::unordered_map<Node, bool> &visited, int &time, Dfs::FunctionExt func) {
 	int opened = ++time;
 	visited[n] = true;
 
@@ -58,63 +53,41 @@ static bool dfs2_impl(const T &graph, const Node &n, const Node &p, std::unorder
 	return func(n, p, opened, ++time);
 }
 
-void Dfs::dfs(const Graph &graph, const Node &start, Dfs::Function func)
-{
-	Data data = { start, func, nullptr };
-	graph.getData().Accept(static_cast<void*>(&data), DFS);
+void Dfs::dfs(const Graph &graph, const Node &start, Dfs::Function func) {
+	getInstance().dispatch(graph.getData(), start, func);
 }
 
-void Dfs::dfs(const Graph &graph, const Node &start, Dfs::FunctionExt func)
-{
-	Data data = { start, nullptr, func };
-	graph.getData().Accept(static_cast<void*>(&data), DFS);
+void Dfs::dfs(const Graph &graph, const Node &start, Dfs::FunctionExt func) {
+	getInstance().dispatch(graph.getData(), start, func);
 }
 
-void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::Function func)
-{
+void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::Function func) {
 	dfs_impl(graph, start, func);
 }
 
-void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::FunctionExt func)
-{
+auto DfsDirectedGraph1 = Dfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Dfs::Function>::RegistratorWrapper<void, graph::DirectedGraph>(Dfs::getInstance(), Dfs::dfs);
+
+void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::FunctionExt func) {
 	int time = 0;
 	std::unordered_map<Node, bool> visited;
 	dfs2_impl(graph, start, start, visited, time, func);
 }
 
-void Dfs::dfs(const UndirectedGraph &graph, const Node &start, Dfs::Function func)
-{
+auto DfsDirectedGraph2 = Dfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Dfs::FunctionExt>::RegistratorWrapper<void, graph::DirectedGraph>(Dfs::getInstance(), Dfs::dfs);
+
+void Dfs::dfs(const UndirectedGraph &graph, const Node &start, Dfs::Function func) {
 	dfs_impl(graph, start, func);
 }
 
-void Dfs::dfs(const UndirectedGraph &graph, const Node &start, Dfs::FunctionExt func)
-{
+auto DfsUndirectedGraph1 = Dfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Dfs::Function>::RegistratorWrapper<void, graph::UndirectedGraph>(Dfs::getInstance(), Dfs::dfs);
+
+void Dfs::dfs(const UndirectedGraph &graph, const Node &start, Dfs::FunctionExt func) {
 	int time = 0;
 	std::unordered_map<Node, bool> visited;
 	dfs2_impl(graph, start, start, visited, time, func);
 }
 
-void Dfs::Visit(void *data, const DirectedGraph &graph) const
-{
-	Data d = *static_cast<Data*>(data);
-	if (d.func) {
-		dfs(graph, d.start, d.func);
-	} else if (d.func2) {
-		dfs(graph, d.start, d.func2);
-	}
-}
-
-void Dfs::Visit(void *data, const UndirectedGraph &graph) const
-{
-	Data d = *static_cast<Data*>(data);
-	if (d.func) {
-		dfs(graph, d.start, d.func);
-	} else if (d.func2) {
-		dfs(graph, d.start, d.func2);
-	}
-}
-
-const Dfs Dfs::DFS;
+auto DfsUndirectedGraph2 = Dfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Dfs::FunctionExt>::RegistratorWrapper<void, graph::UndirectedGraph>(Dfs::getInstance(), Dfs::dfs);
 
 } // namespace traverse
 
diff --git a/alib2algo/src/graph/traverse/Dfs.h b/alib2algo/src/graph/traverse/Dfs.h
index 532b53ba9d4548132cfa28d6a602581735319b70..32d5467c51abaa22132844019535a853e0cc48fc 100644
--- a/alib2algo/src/graph/traverse/Dfs.h
+++ b/alib2algo/src/graph/traverse/Dfs.h
@@ -1,25 +1,24 @@
 #ifndef GRAPH_DFS_H_
 #define GRAPH_DFS_H_
 
+#include <common/multipleDispatch.hpp>
 #include <graph/Graph.h>
 #include <graph/directed/DirectedGraph.h>
 #include <graph/undirected/UndirectedGraph.h>
 
-namespace graph
-{
+namespace graph {
 
-namespace traverse
-{
+namespace traverse {
 
 // func is called for each visited node, traversal stops when returning false
 //
 // bool Function(const Node &node);
 // bool FunctionExt(const Node &node, const Node &predecessor, int openTime, int closeTime);
 
-class Dfs : public graph::VisitableGraphBase::const_visitor_type
-{
+class Dfs : public std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&)>>, public std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&, const Node&, int, int)>> {
 public:
-	Dfs() {}
+	using std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&)>>::dispatch;
+	using std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&, const Node&, int, int)>>::dispatch;
 
 	typedef std::function<bool(const Node&)> Function;
 	typedef std::function<bool(const Node&, const Node&, int, int)> FunctionExt;
@@ -32,11 +31,10 @@ public:
 	static void dfs(const UndirectedGraph &graph, const Node &start, Function func);
 	static void dfs(const UndirectedGraph &graph, const Node &start, FunctionExt func);
 
-private:
-	void Visit(void *data, const DirectedGraph &graph) const;
-	void Visit(void *data, const UndirectedGraph &graph) const;
-
-	static const Dfs DFS;
+	static Dfs& getInstance() {
+		static Dfs res;
+		return res;
+	}
 };
 
 } // namespace traverse
diff --git a/alib2algo/src/regexp/transform/RegExpIterate.h b/alib2algo/src/regexp/transform/RegExpIterate.h
index 66e137d2160ce55f1294f966f49f7d6253edbe19..cb31310be5c794ebd1f26c7e4a88699bb2b7820a 100644
--- a/alib2algo/src/regexp/transform/RegExpIterate.h
+++ b/alib2algo/src/regexp/transform/RegExpIterate.h
@@ -14,8 +14,7 @@
 #include <regexp/formal/FormalRegExp.h>
 #include <regexp/unbounded/UnboundedRegExp.h>
 
-namespace regexp
-{
+namespace regexp {
 
 /**
  * Iterates two regexpses
diff --git a/alib2algo/test-src/graph/traverse/BfsTest.cpp b/alib2algo/test-src/graph/traverse/BfsTest.cpp
index 4594c57fad4e3d397747f00d3451ae5e5f367544..66abaf41847e31bad83db5c85f82c7951c4a1475 100644
--- a/alib2algo/test-src/graph/traverse/BfsTest.cpp
+++ b/alib2algo/test-src/graph/traverse/BfsTest.cpp
@@ -182,7 +182,9 @@ void GraphBfsTest::testBfs2()
 	distances.clear();
 	predecessors.clear();
 
-	graph::traverse::Bfs::bfs(dg, n1, [&](const graph::Node &n, const graph::Node &p, int d) {
+	graph::Graph g(dg);
+
+	graph::traverse::Bfs::bfs(g, n1, [&](const graph::Node &n, const graph::Node &p, int d) {
 		distances[n] = d;
 		predecessors.insert(std::make_pair(n, p));
 		return true;
@@ -210,7 +212,9 @@ void GraphBfsTest::testBfs2()
 	distances.clear();
 	predecessors.clear();
 
-	graph::traverse::Bfs::bfs(ug, n1, [&](const graph::Node &n, const graph::Node &p, int d) {
+	graph::Graph g2(ug);
+
+	graph::traverse::Bfs::bfs(g2, n1, [&](const graph::Node &n, const graph::Node &p, int d) {
 		distances[n] = d;
 		predecessors.insert(std::make_pair(n, p));
 		return true;
diff --git a/alib2algo/test-src/graph/traverse/DfsTest.cpp b/alib2algo/test-src/graph/traverse/DfsTest.cpp
index 90db9b35d90efb47dfa80e585d7e804833d869bb..54ce021370fe0876e7925d405eec22e5c91834ff 100644
--- a/alib2algo/test-src/graph/traverse/DfsTest.cpp
+++ b/alib2algo/test-src/graph/traverse/DfsTest.cpp
@@ -184,7 +184,9 @@ void GraphDfsTest::testDfs2()
 	closed.clear();
 	predecessors.clear();
 
-	graph::traverse::Dfs::dfs(dg, n1, [&](const graph::Node &n, const graph::Node &p, int o, int c) {
+	graph::Graph g(dg);
+
+	graph::traverse::Dfs::dfs(g, n1, [&](const graph::Node &n, const graph::Node &p, int o, int c) {
 		counter++;
 		opened[n] = o;
 		closed[n] = c;
@@ -213,7 +215,9 @@ void GraphDfsTest::testDfs2()
 	closed.clear();
 	predecessors.clear();
 
-	graph::traverse::Dfs::dfs(ug, n1, [&](const graph::Node &n, const graph::Node &p, int o, int c) {
+	graph::Graph g2(ug);
+
+	graph::traverse::Dfs::dfs(g2, n1, [&](const graph::Node &n, const graph::Node &p, int o, int c) {
 		counter++;
 		opened[n] = o;
 		closed[n] = c;
diff --git a/alib2data/src/common/multipleDispatch.hpp b/alib2data/src/common/multipleDispatch.hpp
index 6276f0c1d6a3224fa96ee1fbe3932d07f023b1f1..84a00a59782b7e5adf4b8139dcfad16a1ae31e13 100644
--- a/alib2data/src/common/multipleDispatch.hpp
+++ b/alib2data/src/common/multipleDispatch.hpp
@@ -134,6 +134,45 @@ public:
 
 };
 
+template<class ReturnType, class FirstParameterType, class FirstStaticParamType, class SecondStaticParamType>
+class SingleDispatch2LastStaticParams {
+public:
+	class RegistratorWrapperBase {
+	public:
+		virtual ReturnType eval(const FirstParameterType&, FirstStaticParamType, SecondStaticParamType) = 0;
+
+	};
+
+private:
+	typedef SingleDispatch2LastStaticParams<ReturnType, FirstParameterType, FirstStaticParamType, SecondStaticParamType> SelfType;
+
+	std::map<long long, typename SelfType::RegistratorWrapperBase*> registeredFunctions;
+
+public:
+	template<class RealReturnType, class RealFirstParameterType>
+	class RegistratorWrapper : public RegistratorWrapperBase {
+		std::function<RealReturnType(const RealFirstParameterType&, FirstStaticParamType, SecondStaticParamType)> callback;
+
+	public:
+		ReturnType eval(const FirstParameterType& first, FirstStaticParamType res, SecondStaticParamType res2) {
+			return ReturnType(callback((const RealFirstParameterType&) first, res, res2));
+		}
+
+		RegistratorWrapper(SelfType& pool, RealReturnType(*callback)(const RealFirstParameterType&, FirstStaticParamType, SecondStaticParamType)) : 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, FirstStaticParamType res, SecondStaticParamType res2) {
+		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, res2);
+	}
+
+};
+
 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 template<class ReturnType, class ParametersType>