From 349a47ad0e022032e4fcdb6efd3c38d21a300a17 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Thu, 11 Jun 2015 14:29:10 +0200
Subject: [PATCH] simplify graphs design

---
 alib2data/src/graph/GraphToStringComposer.cpp | 30 ++++-----
 alib2data/src/graph/GraphToStringComposer.h   | 12 ++--
 alib2data/src/graph/GraphToXMLComposer.cpp    | 28 ++++-----
 alib2data/src/graph/GraphToXMLComposer.h      |  9 ++-
 alib2data/src/graph/common/GraphElement.cpp   | 16 -----
 alib2data/src/graph/common/GraphElement.h     | 37 -----------
 alib2data/src/graph/common/Node.cpp           | 38 ++++--------
 alib2data/src/graph/common/Node.h             | 31 +++-------
 alib2data/src/graph/directed/DirectedEdge.cpp | 59 ++++++------------
 alib2data/src/graph/directed/DirectedEdge.h   | 32 +++-------
 .../src/graph/undirected/UndirectedEdge.cpp   | 62 ++++++-------------
 .../src/graph/undirected/UndirectedEdge.h     | 32 +++-------
 12 files changed, 109 insertions(+), 277 deletions(-)
 delete mode 100644 alib2data/src/graph/common/GraphElement.cpp
 delete mode 100644 alib2data/src/graph/common/GraphElement.h

diff --git a/alib2data/src/graph/GraphToStringComposer.cpp b/alib2data/src/graph/GraphToStringComposer.cpp
index f08d93d8db..b48f81a48a 100644
--- a/alib2data/src/graph/GraphToStringComposer.cpp
+++ b/alib2data/src/graph/GraphToStringComposer.cpp
@@ -51,29 +51,23 @@ void GraphToStringComposer::Visit(void *data, const UndirectedGraph &graph) cons
 	composeEdgeValues(out, graph);
 }
 
-void GraphToStringComposer::Visit(void *data, const Node &node) const
+void GraphToStringComposer::composeNode(std::ostream& out, const Node &node) const
 {
-	std::ostream &out = *static_cast<std::ostream*>(data);
-
 	alib::stringApi<label::Label>::compose(out, node.getName());
 }
 
-void GraphToStringComposer::Visit(void *data, const DirectedEdge &edge) const
+void GraphToStringComposer::composeEdge(std::ostream& out, const DirectedEdge &edge) const
 {
-	std::ostream &out = *static_cast<std::ostream*>(data);
-
-	edge.getFromNode().Accept(static_cast<void*>(&out), *this);
+	composeNode(out, edge.getFromNode());
 	alib::stringApi<label::Label>::compose(out, edge.getName());
-	edge.getToNode().Accept(static_cast<void*>(&out), *this);
+	composeNode(out, edge.getToNode());
 }
 
-void GraphToStringComposer::Visit(void *data, const UndirectedEdge &edge) const
+void GraphToStringComposer::composeEdge(std::ostream& out, const UndirectedEdge &edge) const
 {
-	std::ostream &out = *static_cast<std::ostream*>(data);
-
-	edge.getFirstNode().Accept(static_cast<void*>(&out), *this);
+	composeNode(out, edge.getFirstNode());
 	alib::stringApi<label::Label>::compose(out, edge.getName());
-	edge.getSecondNode().Accept(static_cast<void*>(&out), *this);
+	composeNode(out, edge.getSecondNode());
 }
 
 void GraphToStringComposer::composeRepresentation(std::ostream &out, REPRESENTATION representation) const
@@ -91,7 +85,7 @@ void GraphToStringComposer::composeNodes(std::ostream &out, const std::set<Node>
 		} else {
 			out << ",";
 		}
-		node.Accept(static_cast<void*>(&out), *this);
+		composeNode(out, node);
 	}
 }
 
@@ -105,7 +99,7 @@ void GraphToStringComposer::composeDirectedEdges(std::ostream &out, const std::s
 		} else {
 			out << ",";
 		}
-		edge.Accept(static_cast<void*>(&out), *this);
+		composeEdge(out, edge);
 	}
 }
 
@@ -119,7 +113,7 @@ void GraphToStringComposer::composeUndirectedEdges(std::ostream &out, const std:
 		} else {
 			out << ",";
 		}
-		edge.Accept(static_cast<void*>(&out), *this);
+		composeEdge(out, edge);
 	}
 }
 
@@ -134,7 +128,7 @@ void GraphToStringComposer::composeNodeValues(std::ostream &out, const T &graph)
 		} else {
 			out << ",";
 		}
-		i.first.Accept(static_cast<void*>(&out), *this);
+		composeNode(out, i.first);
 		out << "=" << i.second;
 	}
 }
@@ -150,7 +144,7 @@ void GraphToStringComposer::composeEdgeValues(std::ostream &out, const T &graph)
 		} else {
 			out << ",";
 		}
-		i.first.Accept(static_cast<void*>(&out), *this);
+		composeEdge(out, i.first);
 		out << "=" << i.second;
 	}
 }
diff --git a/alib2data/src/graph/GraphToStringComposer.h b/alib2data/src/graph/GraphToStringComposer.h
index 0a65d115f9..67a8056b17 100644
--- a/alib2data/src/graph/GraphToStringComposer.h
+++ b/alib2data/src/graph/GraphToStringComposer.h
@@ -12,11 +12,13 @@
 
 #include "Graph.h"
 #include "GraphRepresentation.h"
-#include "common/GraphElement.h"
+#include "common/Node.h"
+#include "directed/DirectedEdge.h"
+#include "undirected/UndirectedEdge.h"
 
 namespace graph {
 
-class GraphToStringComposer : public VisitableGraphBase::const_visitor_type, GraphElement::const_visitor_type
+class GraphToStringComposer : public VisitableGraphBase::const_visitor_type
 {
 public:
 	GraphToStringComposer() {}
@@ -27,9 +29,9 @@ private:
 	void Visit(void *data, const DirectedGraph &graph) const;
 	void Visit(void *data, const UndirectedGraph &graph) const;
 
-	void Visit(void *data, const Node &node) const;
-	void Visit(void *data, const DirectedEdge &edge) const;
-	void Visit(void *data, const UndirectedEdge &edge) const;
+	void composeNode(std::ostream& out, const Node &node) const;
+	void composeEdge(std::ostream& out, const DirectedEdge &edge) const;
+	void composeEdge(std::ostream& out, const UndirectedEdge &edge) const;
 
 	void composeRepresentation(std::ostream &out, REPRESENTATION representation) const;
 	void composeNodes(std::ostream &out, const std::set<Node> &nodes) const;
diff --git a/alib2data/src/graph/GraphToXMLComposer.cpp b/alib2data/src/graph/GraphToXMLComposer.cpp
index 3dc0210634..6cc9087c40 100644
--- a/alib2data/src/graph/GraphToXMLComposer.cpp
+++ b/alib2data/src/graph/GraphToXMLComposer.cpp
@@ -14,48 +14,42 @@
 
 namespace graph {
 
-void GraphToXMLComposer::Visit(void *data, const Node &node) const
+void GraphToXMLComposer::composeNode(std::deque<sax::Token>& out, const Node &node) const
 {
-	std::deque<sax::Token> &out = *static_cast<std::deque<sax::Token>*>(data);
-
 	out.emplace_back("node", sax::Token::TokenType::START_ELEMENT);
 	alib::xmlApi<label::Label>::compose(out, node.getName());
 	out.emplace_back("node", sax::Token::TokenType::END_ELEMENT);
 }
 
-void GraphToXMLComposer::Visit(void *data, const DirectedEdge &edge) const
+void GraphToXMLComposer::composeEdge(std::deque<sax::Token>& out, const DirectedEdge &edge) const
 {
-	std::deque<sax::Token> &out = *static_cast<std::deque<sax::Token>*>(data);
-
 	out.emplace_back("edge", sax::Token::TokenType::START_ELEMENT);
 
 	out.emplace_back("from", sax::Token::TokenType::START_ELEMENT);
-	edge.getFromNode().Accept(static_cast<void*>(&out), *this);
+	composeNode(out, edge.getFromNode());
 	out.emplace_back("from", sax::Token::TokenType::END_ELEMENT);
 
 	alib::xmlApi<label::Label>::compose(out, edge.getName());
 
 	out.emplace_back("to", sax::Token::TokenType::START_ELEMENT);
-	edge.getToNode().Accept(static_cast<void*>(&out), *this);
+	composeNode(out, edge.getToNode());
 	out.emplace_back("to", sax::Token::TokenType::END_ELEMENT);
 
 	out.emplace_back("edge", sax::Token::TokenType::END_ELEMENT);
 }
 
-void GraphToXMLComposer::Visit(void *data, const UndirectedEdge &edge) const
+void GraphToXMLComposer::composeEdge(std::deque<sax::Token>& out, const UndirectedEdge &edge) const
 {
-	std::deque<sax::Token> &out = *static_cast<std::deque<sax::Token>*>(data);
-
 	out.emplace_back("edge", sax::Token::TokenType::START_ELEMENT);
 
 	out.emplace_back("first", sax::Token::TokenType::START_ELEMENT);
-	edge.getFirstNode().Accept(static_cast<void*>(&out), *this);
+	composeNode(out, edge.getFirstNode());
 	out.emplace_back("first", sax::Token::TokenType::END_ELEMENT);
 
 	alib::xmlApi<label::Label>::compose(out, edge.getName());
 
 	out.emplace_back("second", sax::Token::TokenType::START_ELEMENT);
-	edge.getSecondNode().Accept(static_cast<void*>(&out), *this);
+	composeNode(out, edge.getSecondNode());
 	out.emplace_back("second", sax::Token::TokenType::END_ELEMENT);
 
 	out.emplace_back("edge", sax::Token::TokenType::END_ELEMENT);
@@ -108,7 +102,7 @@ void GraphToXMLComposer::composeNodes(std::deque<sax::Token> &out, const std::se
 {
 	out.emplace_back("nodes", sax::Token::TokenType::START_ELEMENT);
 	for (const Node &node : nodes) {
-		node.Accept(static_cast<void*>(&out), *this);
+		composeNode(out, node);
 	}
 	out.emplace_back("nodes", sax::Token::TokenType::END_ELEMENT);
 }
@@ -118,7 +112,7 @@ void GraphToXMLComposer::composeEdges(std::deque<sax::Token> &out, const std::se
 {
 	out.emplace_back("edges", sax::Token::TokenType::START_ELEMENT);
 	for (const auto &edge : edges) {
-		edge.Accept(static_cast<void*>(&out), *this);
+		composeEdge(out, edge);
 	}
 	out.emplace_back("edges", sax::Token::TokenType::END_ELEMENT);
 }
@@ -128,7 +122,7 @@ void GraphToXMLComposer::composeNodeValues(std::deque<sax::Token> &out, const T
 {
 	out.emplace_back("nodevalues", sax::Token::TokenType::START_ELEMENT);
 	for (auto i : graph.nodeValues) {
-		i.first.Accept(static_cast<void*>(&out), *this);
+		composeNode(out, i.first);
 		out.emplace_back("value", sax::Token::TokenType::START_ELEMENT);
 		out.emplace_back(std::itos(i.second), sax::Token::TokenType::CHARACTER);
 		out.emplace_back("value", sax::Token::TokenType::END_ELEMENT);
@@ -141,7 +135,7 @@ void GraphToXMLComposer::composeEdgeValues(std::deque<sax::Token> &out, const T
 {
 	out.emplace_back("edgevalues", sax::Token::TokenType::START_ELEMENT);
 	for (auto &i : graph.edgeValues) {
-		i.first.Accept(static_cast<void*>(&out), *this);
+		composeEdge(out, i.first);
 		out.emplace_back("value", sax::Token::TokenType::START_ELEMENT);
 		out.emplace_back(std::itos(i.second), sax::Token::TokenType::CHARACTER);
 		out.emplace_back("value", sax::Token::TokenType::END_ELEMENT);
diff --git a/alib2data/src/graph/GraphToXMLComposer.h b/alib2data/src/graph/GraphToXMLComposer.h
index 1e7c1b136e..ca2a72d2da 100644
--- a/alib2data/src/graph/GraphToXMLComposer.h
+++ b/alib2data/src/graph/GraphToXMLComposer.h
@@ -12,7 +12,6 @@
 #include <deque>
 
 #include "GraphFeatures.h"
-#include "common/GraphElement.h"
 #include "../sax/Token.h"
 
 namespace alib {
@@ -25,15 +24,15 @@ struct xmlApi;
 namespace graph {
 
 // This class contains methods to print XML representation of graph to the output stream.
-class GraphToXMLComposer : public GraphElement::const_visitor_type
+class GraphToXMLComposer
 {
 public:
 	GraphToXMLComposer() {}
 
 private:
-	void Visit(void *data, const Node &node) const;
-	void Visit(void *data, const DirectedEdge &edge) const;
-	void Visit(void *data, const UndirectedEdge &edge) const;
+	void composeNode(std::deque<sax::Token>& out, const Node &node) const;
+	void composeEdge(std::deque<sax::Token>& out, const DirectedEdge &edge) const;
+	void composeEdge(std::deque<sax::Token>& out, const UndirectedEdge &edge) const;
 
 	void compose(std::deque<sax::Token> &out, const GraphBase &graph) const;
 	void compose(std::deque<sax::Token> &out, const Graph &graph) const;
diff --git a/alib2data/src/graph/common/GraphElement.cpp b/alib2data/src/graph/common/GraphElement.cpp
deleted file mode 100644
index 6f8e7b2387..0000000000
--- a/alib2data/src/graph/common/GraphElement.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * GraphFeatures.h
- *
- *  Created on: Jun 19, 2014
- *      Author: David Rosca
- */
-
-#include "GraphElement.h"
-
-namespace graph {
-
-GraphElement::GraphElement()
-{
-}
-
-} // namespace graph
diff --git a/alib2data/src/graph/common/GraphElement.h b/alib2data/src/graph/common/GraphElement.h
deleted file mode 100644
index 45144351f6..0000000000
--- a/alib2data/src/graph/common/GraphElement.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * GraphFeatures.h
- *
- *  Created on: Jun 19, 2014
- *      Author: David Rosca
- */
-
-#ifndef GRAPH_ELEMENT_H_
-#define GRAPH_ELEMENT_H_
-
-// for std::hash
-#include <string>
-#include <functional>
-
-#include "../../common/visitor.hpp"
-#include "../../object/Object.h"
-
-namespace graph {
-
-class GraphElement;
-
-class Node;
-class DirectedEdge;
-class UndirectedEdge;
-
-// Abstract class representing element in the graph. Can be node or edge.
-typedef std::acceptor_base<GraphElement, Node, DirectedEdge, UndirectedEdge> VisitableGraphElement;
-
-class GraphElement : public alib::base<GraphElement, Node, DirectedEdge, UndirectedEdge>, public VisitableGraphElement
-{
-public:
-	explicit GraphElement();
-};
-
-} // namespace graph
-
-#endif // GRAPH_ELEMENT_H_
diff --git a/alib2data/src/graph/common/Node.cpp b/alib2data/src/graph/common/Node.cpp
index b529fdff68..90efd477ec 100644
--- a/alib2data/src/graph/common/Node.cpp
+++ b/alib2data/src/graph/common/Node.cpp
@@ -42,45 +42,31 @@ Node::Node(const std::string &name)
 {
 }
 
-Node::Node(const Node &other)
-	: name(other.name)
+Node *Node::clone() const
 {
+	return new Node(*this);
 }
 
-Node::Node(Node &&other) noexcept
-	: name(std::move(other.name))
+Node *Node::plunder() &&
 {
+	return new Node(std::move(*this));
 }
 
-Node &Node::operator=(const Node &other)
+const label::Label &Node::getName() const
 {
-	if (this == &other) {
-		return *this;
-	}
-
-	*this = Node(other);
-	return *this;
+	return name;
 }
 
-Node &Node::operator=(Node &&other) noexcept
-{
-	std::swap(name, other.name);
-	return *this;
+bool Node::operator < (const Node& other) const {
+	return this->compare(other) < 0;
 }
 
-GraphElement *Node::clone() const
-{
-	return new Node(*this);
+bool Node::operator == (const Node& other) const {
+	return this->compare(other) == 0;
 }
 
-GraphElement *Node::plunder() &&
-{
-	return new Node(std::move(*this));
-}
-
-const label::Label &Node::getName() const
-{
-	return name;
+bool Node::operator != (const Node& other) const {
+	return !(*this == other);
 }
 
 int Node::compare(const Node &other) const
diff --git a/alib2data/src/graph/common/Node.h b/alib2data/src/graph/common/Node.h
index fd5d4f444e..c9a5ae748e 100644
--- a/alib2data/src/graph/common/Node.h
+++ b/alib2data/src/graph/common/Node.h
@@ -2,12 +2,11 @@
 #define NODE_H_
 
 #include "Macros.h"
-#include "GraphElement.h"
 #include "../../label/Label.h"
 
 namespace graph {
 
-class Node : public std::acceptor<Node, GraphElement, GraphElement>
+class Node
 {
 public:
 	explicit Node();
@@ -17,31 +16,19 @@ public:
 	explicit Node(char character);
 	explicit Node(const std::string &name);
 
-	Node(const Node &other);
-	Node(Node &&other) noexcept;
-	Node &operator=(const Node &other);
-	Node &operator=(Node &&other) noexcept;
-
-	GraphElement *clone() const override;
-	GraphElement *plunder() && override;
+	Node *clone() const;
+	Node *plunder() &&;
 
 	const label::Label &getName() const;
 
-	int compare(const GraphElement &other) const override
-	{
-		return -other.compare(*this);
-	}
-
-	int compare(const Node &other) const override;
-
-	void operator>>(std::ostream &out) const override;
+	bool operator < (const Node& other) const;
+	bool operator == (const Node& other) const;
+	bool operator != (const Node& other) const;
+	int compare(const Node &other) const;
 
-	explicit operator std::string() const override;
+	void operator>>(std::ostream &out) const;
 
-	int selfTypeId() const override
-	{
-		return typeId<Node>();
-	}
+	explicit operator std::string() const;
 
 	friend std::ostream &operator<<(std::ostream &out, const Node &node);
 
diff --git a/alib2data/src/graph/directed/DirectedEdge.cpp b/alib2data/src/graph/directed/DirectedEdge.cpp
index cf5e89a434..027830cb97 100644
--- a/alib2data/src/graph/directed/DirectedEdge.cpp
+++ b/alib2data/src/graph/directed/DirectedEdge.cpp
@@ -86,44 +86,12 @@ DirectedEdge::DirectedEdge(Node &&from, Node &&to, const std::string &name)
 {
 }
 
-DirectedEdge::DirectedEdge(const DirectedEdge &other)
-	: from(other.from)
-	, to(other.to)
-	, name(other.name)
-{
-}
-
-DirectedEdge::DirectedEdge(DirectedEdge &&other) noexcept
-	: from(std::move(other.from))
-	, to(std::move(other.to))
-	, name(std::move(other.name))
-{
-}
-
-DirectedEdge &DirectedEdge::operator=(const DirectedEdge &other)
-{
-	if (this == &other) {
-		return *this;
-	}
-
-	*this = DirectedEdge(other);
-	return *this;
-}
-
-DirectedEdge &DirectedEdge::operator=(DirectedEdge &&other) noexcept
-{
-	std::swap(from, other.from);
-	std::swap(to, other.to);
-	std::swap(name, other.name);
-	return *this;
-}
-
-GraphElement *DirectedEdge::clone() const
+DirectedEdge *DirectedEdge::clone() const
 {
 	return new DirectedEdge(*this);
 }
 
-GraphElement *DirectedEdge::plunder() &&
+DirectedEdge *DirectedEdge::plunder() &&
 {
 	return new DirectedEdge(std::move(*this));
 }
@@ -143,16 +111,25 @@ const label::Label &DirectedEdge::getName() const
 	return name;
 }
 
+bool DirectedEdge::operator < (const DirectedEdge& other) const {
+	return this->compare(other) < 0;
+}
+
+bool DirectedEdge::operator == (const DirectedEdge& other) const {
+	return this->compare(other) == 0;
+}
+
+bool DirectedEdge::operator != (const DirectedEdge& other) const {
+	return !(*this == other);
+}
+
 int DirectedEdge::compare(const DirectedEdge &other) const
 {
 	int res = name.getData().compare(other.name.getData());
-	if (res == 0) {
-		res = from.compare(other.from);
-		if (res == 0) {
-			res = to.compare(other.to);
-		}
-	}
-	return res;
+	if (res != 0) return res;
+	res = from.compare(other.from);
+	if (res != 0) return res;
+	return to.compare(other.to);
 }
 
 void DirectedEdge::operator>>(std::ostream &out) const
diff --git a/alib2data/src/graph/directed/DirectedEdge.h b/alib2data/src/graph/directed/DirectedEdge.h
index 1679a9b0f2..9276ad1a0b 100644
--- a/alib2data/src/graph/directed/DirectedEdge.h
+++ b/alib2data/src/graph/directed/DirectedEdge.h
@@ -8,14 +8,12 @@
 #ifndef DIRECTED_EDGE_H_
 #define DIRECTED_EDGE_H_
 
-#include "../common/GraphElement.h"
 #include "../common/Macros.h"
 #include "../common/Node.h"
 
 namespace graph {
 
-class DirectedEdge : public std::acceptor<DirectedEdge, GraphElement, GraphElement>
-{
+class DirectedEdge {
 public:
 	explicit DirectedEdge();
 	explicit DirectedEdge(const Node &from, const Node &to);
@@ -29,33 +27,21 @@ public:
 	explicit DirectedEdge(const Node &from, const Node &to, const std::string &name);
 	explicit DirectedEdge(Node &&from, Node &&to, const std::string &name);
 
-	DirectedEdge(const DirectedEdge &other);
-	DirectedEdge(DirectedEdge &&other) noexcept;
-	DirectedEdge &operator=(const DirectedEdge &other);
-	DirectedEdge &operator=(DirectedEdge &&other) noexcept;
-
-	GraphElement *clone() const override;
-	GraphElement *plunder() && override;
+	DirectedEdge *clone() const;
+	DirectedEdge *plunder() &&;
 
 	const Node &getFromNode() const;
 	const Node &getToNode() const;
 	const label::Label &getName() const;
 
-	int compare(const GraphElement &other) const override
-	{
-		return -other.compare(*this);
-	}
-
-	int compare(const DirectedEdge &other) const override;
-
-	void operator>>(std::ostream &out) const override;
+	bool operator < (const DirectedEdge& other) const;
+	bool operator == (const DirectedEdge& other) const;
+	bool operator != (const DirectedEdge& other) const;
+	int compare(const DirectedEdge &other) const;
 
-	explicit operator std::string() const override;
+	void operator>>(std::ostream &out) const;
 
-	int selfTypeId() const override
-	{
-		return typeId(*this);
-	}
+	explicit operator std::string() const;
 
 	friend std::ostream &operator<<(std::ostream &out, const DirectedEdge &node);
 
diff --git a/alib2data/src/graph/undirected/UndirectedEdge.cpp b/alib2data/src/graph/undirected/UndirectedEdge.cpp
index 5b7db96e51..3ea3976111 100644
--- a/alib2data/src/graph/undirected/UndirectedEdge.cpp
+++ b/alib2data/src/graph/undirected/UndirectedEdge.cpp
@@ -86,44 +86,12 @@ UndirectedEdge::UndirectedEdge(Node &&first, Node &&second, const std::string &n
 {
 }
 
-UndirectedEdge::UndirectedEdge(const UndirectedEdge &other)
-	: first(other.first)
-	, second(other.second)
-	, name(other.name)
-{
-}
-
-UndirectedEdge::UndirectedEdge(UndirectedEdge &&other) noexcept
-	: first(std::move(other.first))
-	, second(std::move(other.second))
-	, name(std::move(other.name))
-{
-}
-
-UndirectedEdge &UndirectedEdge::operator=(const UndirectedEdge &other)
-{
-	if (this == &other) {
-		return *this;
-	}
-
-	*this = UndirectedEdge(other);
-	return *this;
-}
-
-UndirectedEdge &UndirectedEdge::operator=(UndirectedEdge &&other) noexcept
-{
-	std::swap(first, other.first);
-	std::swap(second, other.second);
-	std::swap(name, other.name);
-	return *this;
-}
-
-GraphElement *UndirectedEdge::clone() const
+UndirectedEdge *UndirectedEdge::clone() const
 {
 	return new UndirectedEdge(*this);
 }
 
-GraphElement *UndirectedEdge::plunder() &&
+UndirectedEdge *UndirectedEdge::plunder() &&
 {
 	return new UndirectedEdge(std::move(*this));
 }
@@ -143,22 +111,28 @@ const label::Label &UndirectedEdge::getName() const
 	return name;
 }
 
+bool UndirectedEdge::operator < (const UndirectedEdge& other) const {
+	return this->compare(other) < 0;
+}
+
+bool UndirectedEdge::operator == (const UndirectedEdge& other) const {
+	return this->compare(other) == 0;
+}
+
+bool UndirectedEdge::operator != (const UndirectedEdge& other) const {
+	return !(*this == other);
+}
+
 int UndirectedEdge::compare(const UndirectedEdge &other) const
 {
 	auto a = sortedNodes();
 	auto b = other.sortedNodes();
 
 	int res = name.getData().compare(other.name.getData());
-	if (res == 0) {
-		if (a.first.compare(b.second) == 0 && a.second.compare(b.first) == 0) {
-			return 0;
-		}
-		res = a.first.compare(b.first);
-		if (res == 0) {
-			res = a.second.compare(b.second);
-		}
-	}
-	return res;
+	if (res != 0) return res;
+	res = a.first.compare(b.first);
+	if (res != 0) return res;
+	return a.second.compare(b.second);
 }
 
 void UndirectedEdge::operator>>(std::ostream &out) const
diff --git a/alib2data/src/graph/undirected/UndirectedEdge.h b/alib2data/src/graph/undirected/UndirectedEdge.h
index 3a751cea1f..c92aebf559 100644
--- a/alib2data/src/graph/undirected/UndirectedEdge.h
+++ b/alib2data/src/graph/undirected/UndirectedEdge.h
@@ -8,14 +8,12 @@
 #ifndef UNDIRECTED_EDGE_H_
 #define UNDIRECTED_EDGE_H_
 
-#include "../common/GraphElement.h"
 #include "../common/Macros.h"
 #include "../common/Node.h"
 
 namespace graph {
 
-class UndirectedEdge : public std::acceptor<UndirectedEdge, GraphElement, GraphElement>
-{
+class UndirectedEdge {
 public:
 	explicit UndirectedEdge();
 	explicit UndirectedEdge(const Node &first, const Node &second);
@@ -29,33 +27,21 @@ public:
 	explicit UndirectedEdge(const Node &first, const Node &second, const std::string &name);
 	explicit UndirectedEdge(Node &&first, Node &&second, const std::string &name);
 
-	UndirectedEdge(const UndirectedEdge &other);
-	UndirectedEdge(UndirectedEdge &&other) noexcept;
-	UndirectedEdge &operator=(const UndirectedEdge &other);
-	UndirectedEdge &operator=(UndirectedEdge &&other) noexcept;
-
-	GraphElement *clone() const override;
-	GraphElement *plunder() && override;
+	UndirectedEdge *clone() const;
+	UndirectedEdge *plunder() &&;
 
 	const Node &getFirstNode() const;
 	const Node &getSecondNode() const;
 	const label::Label &getName() const;
 
-	int compare(const GraphElement &other) const override
-	{
-		return -other.compare(*this);
-	}
-
-	int compare(const UndirectedEdge &other) const override;
-
-	void operator>>(std::ostream &out) const override;
+	bool operator < (const UndirectedEdge& other) const;
+	bool operator == (const UndirectedEdge& other) const;
+	bool operator != (const UndirectedEdge& other) const;
+	int compare(const UndirectedEdge &other) const;
 
-	explicit operator std::string() const override;
+	void operator>>(std::ostream &out) const;
 
-	int selfTypeId() const override
-	{
-		return typeId(*this);
-	}
+	explicit operator std::string() const;
 
 	friend std::ostream &operator<<(std::ostream &out, const UndirectedEdge &node);
 
-- 
GitLab