From 0ab49136a1ca7a56655130aaa2e68f87d636d121 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Sun, 23 Nov 2014 18:25:26 +0100
Subject: [PATCH] std::tie compare capability

---
 alib2data/src/automaton/FSM/CompactNFA.cpp    | 24 +++--------
 alib2data/src/automaton/FSM/DFA.cpp           | 24 +++--------
 alib2data/src/automaton/FSM/EpsilonNFA.cpp    | 24 +++--------
 alib2data/src/automaton/FSM/ExtendedNFA.cpp   | 24 +++--------
 .../automaton/FSM/MultiInitialStateNFA.cpp    | 24 +++--------
 alib2data/src/automaton/FSM/NFA.cpp           | 24 +++--------
 alib2data/src/automaton/PDA/DPDA.cpp          | 32 +++------------
 .../src/automaton/PDA/InputDrivenNPDA.cpp     | 36 +++--------------
 alib2data/src/automaton/PDA/NPDA.cpp          | 32 +++------------
 .../PDA/RealTimeHeightDeterministicDPDA.cpp   | 40 +++----------------
 .../PDA/RealTimeHeightDeterministicNPDA.cpp   | 15 +++----
 alib2data/src/automaton/PDA/SinglePopDPDA.cpp |  9 +----
 alib2data/src/automaton/PDA/SinglePopNPDA.cpp |  9 +----
 .../src/automaton/PDA/VisiblyPushdownDPDA.cpp |  9 +----
 .../src/automaton/PDA/VisiblyPushdownNPDA.cpp |  9 +----
 alib2data/src/automaton/TM/OneTapeDTM.cpp     |  9 +----
 alib2data/src/automaton/common/Shift.h        | 12 ++++++
 alib2data/src/std/compare.hpp                 | 30 ++++++++++++++
 alib2data/src/std/variant.hpp                 |  2 +-
 19 files changed, 108 insertions(+), 280 deletions(-)

diff --git a/alib2data/src/automaton/FSM/CompactNFA.cpp b/alib2data/src/automaton/FSM/CompactNFA.cpp
index 16d53007a8..4717dc0adf 100644
--- a/alib2data/src/automaton/FSM/CompactNFA.cpp
+++ b/alib2data/src/automaton/FSM/CompactNFA.cpp
@@ -165,25 +165,11 @@ std::map<std::pair<State, string::LinearString>, std::set<State>> CompactNFA::ge
 }
 
 int CompactNFA::compare(const CompactNFA& other) const {
-	std::compare<decltype(states)> comp;
-	int res = comp(states, other.states);
-	if(res == 0) {
-		std::compare<decltype(inputAlphabet)> comp;
-		res = comp(inputAlphabet, other.inputAlphabet);
-	}
-	if(res == 0) {
-		std::compare<decltype(initialState)> comp;
-		res = comp(initialState, other.initialState);
-	}
-	if(res == 0) {
-		std::compare<decltype(finalStates)> comp;
-		res = comp(finalStates, other.finalStates);
-	}
-	if(res == 0) {
-		std::compare<decltype(transitions)> comp;
-		res = comp(transitions, other.transitions);
-	}
-	return res;
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
+
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void CompactNFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/DFA.cpp b/alib2data/src/automaton/FSM/DFA.cpp
index 41a93b6dcb..cf5c9eb51c 100644
--- a/alib2data/src/automaton/FSM/DFA.cpp
+++ b/alib2data/src/automaton/FSM/DFA.cpp
@@ -133,25 +133,11 @@ bool DFA::isTotal() const {
 }
 
 int DFA::compare(const DFA& other) const {
-	std::compare<decltype(states)> comp;
-	int res = comp(states, other.states);
-	if(res == 0) {
-		std::compare<decltype(inputAlphabet)> comp;
-		res = comp(inputAlphabet, other.inputAlphabet);
-	}
-	if(res == 0) {
-		std::compare<decltype(initialState)> comp;
-		res = comp(initialState, other.initialState);
-	}
-	if(res == 0) {
-		std::compare<decltype(finalStates)> comp;
-		res = comp(finalStates, other.finalStates);
-	}
-	if(res == 0) {
-		std::compare<decltype(transitions)> comp;
-		res = comp(transitions, other.transitions);
-	}
-	return res;
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
+
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void DFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/EpsilonNFA.cpp b/alib2data/src/automaton/FSM/EpsilonNFA.cpp
index 1dc580bef8..16bde674c8 100644
--- a/alib2data/src/automaton/FSM/EpsilonNFA.cpp
+++ b/alib2data/src/automaton/FSM/EpsilonNFA.cpp
@@ -266,25 +266,11 @@ bool EpsilonNFA::isTotal() const {
 }
 
 int EpsilonNFA::compare(const EpsilonNFA& other) const {
-	std::compare<decltype(states)> comp;
-	int res = comp(states, other.states);
-	if(res == 0) {
-		std::compare<decltype(inputAlphabet)> comp;
-		res = comp(inputAlphabet, other.inputAlphabet);
-	}
-	if(res == 0) {
-		std::compare<decltype(initialState)> comp;
-		res = comp(initialState, other.initialState);
-	}
-	if(res == 0) {
-		std::compare<decltype(finalStates)> comp;
-		res = comp(finalStates, other.finalStates);
-	}
-	if(res == 0) {
-		std::compare<decltype(transitions)> comp;
-		res = comp(transitions, other.transitions);
-	}
-	return res;
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
+
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void EpsilonNFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.cpp b/alib2data/src/automaton/FSM/ExtendedNFA.cpp
index 3d7d13dfaf..3b6699d2a4 100644
--- a/alib2data/src/automaton/FSM/ExtendedNFA.cpp
+++ b/alib2data/src/automaton/FSM/ExtendedNFA.cpp
@@ -177,25 +177,11 @@ std::map<std::pair<State, regexp::RegExp>, std::set<State> > ExtendedNFA::getTra
 }
 
 int ExtendedNFA::compare(const ExtendedNFA& other) const {
-	std::compare<decltype(states)> comp;
-	int res = comp(states, other.states);
-	if(res == 0) {
-		std::compare<decltype(inputAlphabet)> comp;
-		res = comp(inputAlphabet, other.inputAlphabet);
-	}
-	if(res == 0) {
-		std::compare<decltype(initialState)> comp;
-		res = comp(initialState, other.initialState);
-	}
-	if(res == 0) {
-		std::compare<decltype(finalStates)> comp;
-		res = comp(finalStates, other.finalStates);
-	}
-	if(res == 0) {
-		std::compare<decltype(transitions)> comp;
-		res = comp(transitions, other.transitions);
-	}
-	return res;
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
+
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void ExtendedNFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp b/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp
index 4b505cb25a..d0b9c757bd 100644
--- a/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp
+++ b/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp
@@ -156,25 +156,11 @@ unsigned MultiInitialStateNFA::transitionsSize() const {
 }
 
 int MultiInitialStateNFA::compare(const MultiInitialStateNFA& other) const {
-	std::compare<decltype(states)> comp;
-	int res = comp(states, other.states);
-	if(res == 0) {
-		std::compare<decltype(inputAlphabet)> comp;
-		res = comp(inputAlphabet, other.inputAlphabet);
-	}
-	if(res == 0) {
-		std::compare<decltype(initialStates)> comp;
-		res = comp(initialStates, other.initialStates);
-	}
-	if(res == 0) {
-		std::compare<decltype(finalStates)> comp;
-		res = comp(finalStates, other.finalStates);
-	}
-	if(res == 0) {
-		std::compare<decltype(transitions)> comp;
-		res = comp(transitions, other.transitions);
-	}
-	return res;
+	auto first = std::tie(states, inputAlphabet, initialStates, finalStates, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.transitions);
+
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void MultiInitialStateNFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/NFA.cpp b/alib2data/src/automaton/FSM/NFA.cpp
index f9df9181e9..402e9bd1b2 100644
--- a/alib2data/src/automaton/FSM/NFA.cpp
+++ b/alib2data/src/automaton/FSM/NFA.cpp
@@ -139,25 +139,11 @@ unsigned NFA::transitionsSize() const {
 }
 
 int NFA::compare(const NFA& other) const {
-	std::compare<decltype(states)> comp;
-	int res = comp(states, other.states);
-	if(res == 0) {
-		std::compare<decltype(inputAlphabet)> comp;
-		res = comp(inputAlphabet, other.inputAlphabet);
-	}
-	if(res == 0) {
-		std::compare<decltype(initialState)> comp;
-		res = comp(initialState, other.initialState);
-	}
-	if(res == 0) {
-		std::compare<decltype(finalStates)> comp;
-		res = comp(finalStates, other.finalStates);
-	}
-	if(res == 0) {
-		std::compare<decltype(transitions)> comp;
-		res = comp(transitions, other.transitions);
-	}
-	return res;
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
+
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void NFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/DPDA.cpp b/alib2data/src/automaton/PDA/DPDA.cpp
index 2b16f016c8..bd5199bac1 100644
--- a/alib2data/src/automaton/PDA/DPDA.cpp
+++ b/alib2data/src/automaton/PDA/DPDA.cpp
@@ -223,33 +223,11 @@ std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std:
 }
 
 int DPDA::compare(const DPDA& other) const {
-	std::compare<decltype(states)> comp;
-	int res = comp(states, other.states);
-	if(res == 0) {
-		std::compare<decltype(inputAlphabet)> comp;
-		res = comp(inputAlphabet, other.inputAlphabet);
-	}
-	if(res == 0) {
-		std::compare<decltype(initialState)> comp;
-		res = comp(initialState, other.initialState);
-	}
-	if(res == 0) {
-		std::compare<decltype(finalStates)> comp;
-		res = comp(finalStates, other.finalStates);
-	}
-	if(res == 0) {
-		std::compare<decltype(stackAlphabet)> comp;
-		res = comp(stackAlphabet, other.stackAlphabet);
-	}
-	if(res == 0) {
-		std::compare<decltype(initialSymbol)> comp;
-		res = comp(initialSymbol, other.initialSymbol);
-	}
-	if(res == 0) {
-		std::compare<decltype(transitions)> comp;
-		res = comp(transitions, other.transitions);
-	}
-	return res;
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, stackAlphabet, initialSymbol, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.stackAlphabet, other.initialSymbol, other.transitions);
+
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void DPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp b/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp
index 8f263d6f7d..3e5a751895 100644
--- a/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp
+++ b/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp
@@ -175,37 +175,11 @@ bool InputDrivenNPDA::isDeterministic() const {
 }
 
 int InputDrivenNPDA::compare(const InputDrivenNPDA& other) const {
-	std::compare<decltype(states)> comp;
-	int res = comp(states, other.states);
-	if(res == 0) {
-		std::compare<decltype(inputAlphabet)> comp;
-		res = comp(inputAlphabet, other.inputAlphabet);
-	}
-	if(res == 0) {
-		std::compare<decltype(initialStates)> comp;
-		res = comp(initialStates, other.initialStates);
-	}
-	if(res == 0) {
-		std::compare<decltype(finalStates)> comp;
-		res = comp(finalStates, other.finalStates);
-	}
-	if(res == 0) {
-		std::compare<decltype(stackAlphabet)> comp;
-		res = comp(stackAlphabet, other.stackAlphabet);
-	}
-	if(res == 0) {
-		std::compare<decltype(initialSymbol)> comp;
-		res = comp(initialSymbol, other.initialSymbol);
-	}
-	if(res == 0) {
-		std::compare<decltype(inputSymbolToPushdownStoreOperation)> comp;
-		res = comp(inputSymbolToPushdownStoreOperation, other.inputSymbolToPushdownStoreOperation);
-	}
-	if(res == 0) {
-		std::compare<decltype(transitions)> comp;
-		res = comp(transitions, other.transitions);
-	}
-	return res;
+	auto first = std::tie(states, inputAlphabet, initialStates, finalStates, stackAlphabet, initialSymbol, inputSymbolToPushdownStoreOperation, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.stackAlphabet, other.initialSymbol, other.inputSymbolToPushdownStoreOperation, other.transitions);
+
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void InputDrivenNPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/NPDA.cpp b/alib2data/src/automaton/PDA/NPDA.cpp
index a95026b83b..792d9f7200 100644
--- a/alib2data/src/automaton/PDA/NPDA.cpp
+++ b/alib2data/src/automaton/PDA/NPDA.cpp
@@ -134,33 +134,11 @@ const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>
 }
 
 int NPDA::compare(const NPDA& other) const {
-	std::compare<decltype(states)> comp;
-	int res = comp(states, other.states);
-	if(res == 0) {
-		std::compare<decltype(inputAlphabet)> comp;
-		res = comp(inputAlphabet, other.inputAlphabet);
-	}
-	if(res == 0) {
-		std::compare<decltype(initialStates)> comp;
-		res = comp(initialStates, other.initialStates);
-	}
-	if(res == 0) {
-		std::compare<decltype(finalStates)> comp;
-		res = comp(finalStates, other.finalStates);
-	}
-	if(res == 0) {
-		std::compare<decltype(stackAlphabet)> comp;
-		res = comp(stackAlphabet, other.stackAlphabet);
-	}
-	if(res == 0) {
-		std::compare<decltype(initialSymbols)> comp;
-		res = comp(initialSymbols, other.initialSymbols);
-	}
-	if(res == 0) {
-		std::compare<decltype(transitions)> comp;
-		res = comp(transitions, other.transitions);
-	}
-	return res;
+	auto first = std::tie(states, inputAlphabet, initialStates, finalStates, stackAlphabet, initialSymbols, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.stackAlphabet, other.initialSymbols, other.transitions);
+
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void NPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp
index 453c9b3a34..a85d75bb93 100644
--- a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp
+++ b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp
@@ -367,41 +367,11 @@ const std::map<std::pair<State, std::variant<string::Epsilon, alphabet::Symbol>>
 }
 
 int RealTimeHeightDeterministicDPDA::compare(const RealTimeHeightDeterministicDPDA& other) const {
-	std::compare<decltype(states)> comp;
-	int res = comp(states, other.states);
-	if(res == 0) {
-		std::compare<decltype(inputAlphabet)> comp;
-		res = comp(inputAlphabet, other.inputAlphabet);
-	}
-	if(res == 0) {
-		std::compare<decltype(initialState)> comp;
-		res = comp(initialState, other.initialState);
-	}
-	if(res == 0) {
-		std::compare<decltype(finalStates)> comp;
-		res = comp(finalStates, other.finalStates);
-	}
-	if(res == 0) {
-		std::compare<decltype(stackAlphabet)> comp;
-		res = comp(stackAlphabet, other.stackAlphabet);
-	}
-	if(res == 0) {
-		std::compare<decltype(bottomOfTheStackSymbol)> comp;
-		res = comp(bottomOfTheStackSymbol, other.bottomOfTheStackSymbol);
-	}
-	if(res == 0) {
-		std::compare<decltype(callTransitions)> comp;
-		res = comp(callTransitions, other.callTransitions);
-	}
-	if(res == 0) {
-		std::compare<decltype(returnTransitions)> comp;
-		res = comp(returnTransitions, other.returnTransitions);
-	}
-	if(res == 0) {
-		std::compare<decltype(localTransitions)> comp;
-		res = comp(localTransitions, other.localTransitions);
-	}
-	return res;
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, stackAlphabet, bottomOfTheStackSymbol, callTransitions, returnTransitions, localTransitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.stackAlphabet, other.bottomOfTheStackSymbol, other.callTransitions, other.returnTransitions, other.localTransitions);
+
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void RealTimeHeightDeterministicDPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicNPDA.cpp b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicNPDA.cpp
index 8a5f75eade..fad698ce43 100644
--- a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicNPDA.cpp
+++ b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicNPDA.cpp
@@ -246,28 +246,23 @@ bool RealTimeHeightDeterministicNPDA::removeLocalTransition(const State& from, c
 }
 
 const std::map<std::pair<State, std::variant<string::Epsilon, alphabet::Symbol>>, std::set<std::pair<State, alphabet::Symbol> > >& RealTimeHeightDeterministicNPDA::getCallTransitions() const {
-		return callTransitions;
+	return callTransitions;
 }
 
 const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol>, std::set<State> >& RealTimeHeightDeterministicNPDA::getReturnTransitions() const {
-		return returnTransitions;
+	return returnTransitions;
 }
 
 const std::map<std::pair<State, std::variant<string::Epsilon, alphabet::Symbol>>, std::set<State> >& RealTimeHeightDeterministicNPDA::getLocalTransitions() const {
-		return localTransitions;
+	return localTransitions;
 }
 
 int RealTimeHeightDeterministicNPDA::compare(const RealTimeHeightDeterministicNPDA& other) const {
 	auto first = std::tie(states, inputAlphabet, initialStates, finalStates, stackAlphabet, bottomOfTheStackSymbol, callTransitions, returnTransitions, localTransitions);
 	auto second = std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.stackAlphabet, other.bottomOfTheStackSymbol, other.callTransitions, other.returnTransitions, other.localTransitions);
 
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
-	}
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void RealTimeHeightDeterministicNPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/SinglePopDPDA.cpp b/alib2data/src/automaton/PDA/SinglePopDPDA.cpp
index be45694060..c7ff484307 100644
--- a/alib2data/src/automaton/PDA/SinglePopDPDA.cpp
+++ b/alib2data/src/automaton/PDA/SinglePopDPDA.cpp
@@ -172,13 +172,8 @@ int SinglePopDPDA::compare(const SinglePopDPDA& other) const {
 	auto first = std::tie(states, inputAlphabet, initialState, finalStates, stackAlphabet, initialSymbol, transitions);
 	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.stackAlphabet, other.initialSymbol, other.transitions);
 
-	if(first == second) {
-		return 0;
-	} else if(first == second) {
-		return -1;
-	} else {
-		return 1;
-	}
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void SinglePopDPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/SinglePopNPDA.cpp b/alib2data/src/automaton/PDA/SinglePopNPDA.cpp
index b4040aa83a..9fc7f474b5 100644
--- a/alib2data/src/automaton/PDA/SinglePopNPDA.cpp
+++ b/alib2data/src/automaton/PDA/SinglePopNPDA.cpp
@@ -133,13 +133,8 @@ int SinglePopNPDA::compare(const SinglePopNPDA& other) const {
 	auto first = std::tie(states, inputAlphabet, initialStates, finalStates, stackAlphabet, initialSymbols, transitions);
 	auto second = std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.stackAlphabet, other.initialSymbols, other.transitions);
 
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
-	}
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void SinglePopNPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/VisiblyPushdownDPDA.cpp b/alib2data/src/automaton/PDA/VisiblyPushdownDPDA.cpp
index ec13165a9e..71d9976031 100644
--- a/alib2data/src/automaton/PDA/VisiblyPushdownDPDA.cpp
+++ b/alib2data/src/automaton/PDA/VisiblyPushdownDPDA.cpp
@@ -268,13 +268,8 @@ int VisiblyPushdownDPDA::compare(const VisiblyPushdownDPDA& other) const {
 	auto first = std::tie(states, callInputAlphabet, returnInputAlphabet, localInputAlphabet, initialState, finalStates, stackAlphabet, bottomOfTheStackSymbol, callTransitions, returnTransitions, localTransitions);
 	auto second = std::tie(other.states, other.callInputAlphabet, other.returnInputAlphabet, other.localInputAlphabet, other.initialState, other.finalStates, other.stackAlphabet, other.bottomOfTheStackSymbol, other.callTransitions, other.returnTransitions, other.localTransitions);
 
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
-	}
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void VisiblyPushdownDPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/VisiblyPushdownNPDA.cpp b/alib2data/src/automaton/PDA/VisiblyPushdownNPDA.cpp
index b953fedbbb..e72e3e0b48 100644
--- a/alib2data/src/automaton/PDA/VisiblyPushdownNPDA.cpp
+++ b/alib2data/src/automaton/PDA/VisiblyPushdownNPDA.cpp
@@ -201,13 +201,8 @@ int VisiblyPushdownNPDA::compare(const VisiblyPushdownNPDA& other) const {
 	auto first = std::tie(states, callInputAlphabet, returnInputAlphabet, localInputAlphabet, initialStates, finalStates, stackAlphabet, bottomOfTheStackSymbol, callTransitions, returnTransitions, localTransitions);
 	auto second = std::tie(other.states, other.callInputAlphabet, other.returnInputAlphabet, other.localInputAlphabet, other.initialStates, other.finalStates, other.stackAlphabet, other.bottomOfTheStackSymbol, other.callTransitions, other.returnTransitions, other.localTransitions);
 
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
-	}
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void VisiblyPushdownNPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/TM/OneTapeDTM.cpp b/alib2data/src/automaton/TM/OneTapeDTM.cpp
index 45497fff24..24078fae6d 100644
--- a/alib2data/src/automaton/TM/OneTapeDTM.cpp
+++ b/alib2data/src/automaton/TM/OneTapeDTM.cpp
@@ -118,13 +118,8 @@ int OneTapeDTM::compare(const OneTapeDTM& other) const {
 	auto first = std::tie(states, inputAlphabet, initialState, finalStates, tapeAlphabet, blankSymbol, transitions);
 	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.tapeAlphabet, other.blankSymbol, other.transitions);
 
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
-	}
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
 }
 
 void OneTapeDTM::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/common/Shift.h b/alib2data/src/automaton/common/Shift.h
index 7d854a2c56..751783b426 100644
--- a/alib2data/src/automaton/common/Shift.h
+++ b/alib2data/src/automaton/common/Shift.h
@@ -9,6 +9,7 @@
 #define SHIFT_H_
 
 #include <string>
+#include "../../std/compare.hpp"
 
 namespace automaton {
 
@@ -23,4 +24,15 @@ extern std::string SHIFT_NAMES[4];
 
 } /* namespace automaton */
 
+namespace std {
+
+template<>
+struct compare<automaton::Shift> {
+	int operator()(const automaton::Shift& first, const automaton::Shift& second) {
+		return first - second;
+	}
+};
+
+} /* namespace std */
+
 #endif /* SHIFT_H_ */
diff --git a/alib2data/src/std/compare.hpp b/alib2data/src/std/compare.hpp
index 8d8741a658..4e1e780cb0 100644
--- a/alib2data/src/std/compare.hpp
+++ b/alib2data/src/std/compare.hpp
@@ -128,6 +128,36 @@ struct compare<string> {
 	}
 };
 
+
+template<int I, typename Tie>
+struct compareTieHelper;
+
+template<int I, typename Tie>
+struct compareTieHelper {
+	static int compHelp(const Tie& t1, const Tie& t2) {
+		compare<typename std::remove_const<typename std::remove_reference<typename tuple_element<I, Tie>::type>::type>::type> comp;
+		int res = comp(std::get<I>(t1), std::get<I>(t2));
+		if(res != 0) return res;
+		return compareTieHelper<I - 1, Tie>::compHelp(t1, t2);
+	}
+};
+
+template<class Tie>
+struct compareTieHelper<0, Tie> {
+	static int compHelp(const Tie& t1, const Tie& t2) {
+		compare<typename std::remove_const<typename std::remove_reference<typename tuple_element<0, Tie>::type>::type>::type> comp;
+		return comp(std::get<0>(t1), std::get<0>(t2));
+	}
+};
+
+
+template<typename ... Ts>
+struct compare<tuple<Ts&...>> {
+	int operator()(const tuple<Ts&...>& first, const tuple<Ts&...>& second) const {
+		return compareTieHelper<tuple_size<std::tuple<Ts&...>>::value - 1, std::tuple<Ts&...>>::compHelp(first, second);
+	}
+};
+
 } /* namespace std */
 
 #endif /* COMPARE_HPP_ */
diff --git a/alib2data/src/std/variant.hpp b/alib2data/src/std/variant.hpp
index df432ef365..7a6dc3bc10 100644
--- a/alib2data/src/std/variant.hpp
+++ b/alib2data/src/std/variant.hpp
@@ -255,7 +255,7 @@ public:
 
 template<typename ... Ts>
 struct compare<variant<Ts...>> {
-	int operator()(const variant<Ts...>& first, const variant<Ts...>& second) {
+	int operator()(const variant<Ts...>& first, const variant<Ts...>& second) const {
 		return first.compare(second);
 	}
 };
-- 
GitLab