diff --git a/alib2data/src/automaton/FSM/DFA.cpp b/alib2data/src/automaton/FSM/DFA.cpp
index ec5169eedaccea3d45258bdc3f1652448d8124e9..41a93b6dcbfbd6548c9dda5651fa037f76a22bd7 100644
--- a/alib2data/src/automaton/FSM/DFA.cpp
+++ b/alib2data/src/automaton/FSM/DFA.cpp
@@ -133,16 +133,25 @@ bool DFA::isTotal() const {
 }
 
 int DFA::compare(const DFA& other) const {
-	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
-	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	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;
 }
 
 void DFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/EpsilonNFA.cpp b/alib2data/src/automaton/FSM/EpsilonNFA.cpp
index c053207f2272d7a16ed01759d7f3347de36c6fea..1dc580bef8d5e940ced2269775aa8a49d69a4e5b 100644
--- a/alib2data/src/automaton/FSM/EpsilonNFA.cpp
+++ b/alib2data/src/automaton/FSM/EpsilonNFA.cpp
@@ -266,16 +266,25 @@ bool EpsilonNFA::isTotal() const {
 }
 
 int EpsilonNFA::compare(const EpsilonNFA& other) const {
-	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
-	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	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;
 }
 
 void EpsilonNFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.cpp b/alib2data/src/automaton/FSM/ExtendedNFA.cpp
index 663920663a37efd73da99f2c3df1f5cd5fecf2a2..3d7d13dfaf582d60663c3f322cb8fdb9192c289a 100644
--- a/alib2data/src/automaton/FSM/ExtendedNFA.cpp
+++ b/alib2data/src/automaton/FSM/ExtendedNFA.cpp
@@ -177,16 +177,25 @@ std::map<std::pair<State, regexp::RegExp>, std::set<State> > ExtendedNFA::getTra
 }
 
 int ExtendedNFA::compare(const ExtendedNFA& other) const {
-	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
-	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	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;
 }
 
 void ExtendedNFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp b/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp
index fbe13322e8cb40d3f0cf3b59f356a1452ff5f275..4b505cb25ab503eba25cd061566955f905eb5a82 100644
--- a/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp
+++ b/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp
@@ -156,16 +156,25 @@ unsigned MultiInitialStateNFA::transitionsSize() const {
 }
 
 int MultiInitialStateNFA::compare(const MultiInitialStateNFA& other) const {
-	auto first = std::tie(states, inputAlphabet, initialStates, finalStates, transitions);
-	auto second = std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.transitions);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	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;
 }
 
 void MultiInitialStateNFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/NFA.cpp b/alib2data/src/automaton/FSM/NFA.cpp
index 72ee67a7facba93aafdec6ef2e3dd4a869984a21..f9df9181e96c03565d551be8e069206773dc8fbd 100644
--- a/alib2data/src/automaton/FSM/NFA.cpp
+++ b/alib2data/src/automaton/FSM/NFA.cpp
@@ -139,16 +139,25 @@ unsigned NFA::transitionsSize() const {
 }
 
 int NFA::compare(const NFA& other) const {
-	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
-	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	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;
 }
 
 void NFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/DPDA.cpp b/alib2data/src/automaton/PDA/DPDA.cpp
index 85bd138fe4e22d020d7911c0fa93854215ff31b7..2b16f016c8519f52cfd750017b04fd21562adb00 100644
--- a/alib2data/src/automaton/PDA/DPDA.cpp
+++ b/alib2data/src/automaton/PDA/DPDA.cpp
@@ -223,16 +223,33 @@ std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std:
 }
 
 int DPDA::compare(const DPDA& 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(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;
 }
 
 void DPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp b/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp
index c6fa402b502d1155e6fa5b4e76a0856622369644..8f263d6f7d008b50aeaeaafed9d345cbef9b786c 100644
--- a/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp
+++ b/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp
@@ -175,16 +175,37 @@ bool InputDrivenNPDA::isDeterministic() const {
 }
 
 int InputDrivenNPDA::compare(const InputDrivenNPDA& other) const {
-	auto first = std::tie(states, inputAlphabet, initialStates, finalStates, transitions);
-	auto second = std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.transitions);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	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;
 }
 
 void InputDrivenNPDA::operator>>(std::ostream& out) const {
@@ -193,7 +214,10 @@ void InputDrivenNPDA::operator>>(std::ostream& out) const {
 		<< " inputAlphabet = " << inputAlphabet
 		<< " initialStates = " << initialStates
 		<< " finalStates = " << finalStates
+		<< " stackAlphabet = " << stackAlphabet
+		<< " initialSymbol = " << initialSymbol
 		<< " transitions = " << transitions
+		<< " inputSymbolToPushdownStoreOperation = " << inputSymbolToPushdownStoreOperation
 		<< ")";
 }
 
diff --git a/alib2data/src/automaton/PDA/NPDA.cpp b/alib2data/src/automaton/PDA/NPDA.cpp
index 5407aaaed8f383459325dfe14df9fa5c54b356ae..a95026b83b318de8dc2d2317c02731c5bc65b900 100644
--- a/alib2data/src/automaton/PDA/NPDA.cpp
+++ b/alib2data/src/automaton/PDA/NPDA.cpp
@@ -134,16 +134,33 @@ const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>
 }
 
 int NPDA::compare(const NPDA& 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(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;
 }
 
 void NPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp
index 0b44a8fafba36597dd97bd62d9eebb74b9764ab7..453c9b3a34251d473c20c0bbdd29aa155f6bebf8 100644
--- a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp
+++ b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp
@@ -367,16 +367,41 @@ const std::map<std::pair<State, std::variant<string::Epsilon, alphabet::Symbol>>
 }
 
 int RealTimeHeightDeterministicDPDA::compare(const RealTimeHeightDeterministicDPDA& other) const {
-	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);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	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;
 }
 
 void RealTimeHeightDeterministicDPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/std/compare.hpp b/alib2data/src/std/compare.hpp
index fbb2a3dbe46f53336edf1b9be25a8910b543e6cb..8d8741a658373b6e3f7d6031f786c73fac355532 100644
--- a/alib2data/src/std/compare.hpp
+++ b/alib2data/src/std/compare.hpp
@@ -12,6 +12,7 @@
 #include <vector>
 #include <string>
 #include <map>
+#include <tuple>
 
 namespace std {
 
@@ -91,6 +92,35 @@ struct compare<map<T, R>> {
 	}
 };
 
+template<int I, typename Tuple>
+struct compareTupleHelper;
+
+template<int I, typename Tuple>
+struct compareTupleHelper {
+	static int compHelp(const Tuple& t1, const Tuple& t2) {
+		compare<typename tuple_element<I, Tuple>::type> comp;
+		int res = comp(std::get<I>(t1), std::get<I>(t2));
+		if(res != 0) return res;
+		return compareTupleHelper<I - 1, Tuple>::compHelp(t1, t2);
+	}
+};
+
+template<class Tuple>
+struct compareTupleHelper<0, Tuple> {
+	static int compHelp(const Tuple& t1, const Tuple& t2) {
+		compare<typename tuple_element<0, Tuple>::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 compareTupleHelper<tuple_size<std::tuple<Ts...>>::value - 1, std::tuple<Ts...>>::compHelp(first, second);
+	}
+};
+
 template<>
 struct compare<string> {
 	int operator()(const string& first, const string& second) const {
diff --git a/alib2data/src/std/variant.hpp b/alib2data/src/std/variant.hpp
index fc19fc4e4e1b82d3cff460b40323c5079f5fcee0..df432ef3650d826ea9f45ef1f5ed6f4307489f73 100644
--- a/alib2data/src/std/variant.hpp
+++ b/alib2data/src/std/variant.hpp
@@ -13,6 +13,7 @@
 #include <typeinfo>
 #include "type_traits.hpp"
 #include <string>
+#include "compare.hpp"
 
 namespace std {
 
@@ -61,14 +62,6 @@ struct variant_helper<F, Ts...> {
 			variant_helper<Ts...>::move(old_t, old_v, new_v);
 	}
 
-	inline static bool compareEq(size_t this_t, const void * this_v, size_t other_t, const void * other_v)
-	{
-		if (this_t == typeid(F).hash_code())
-			return this_t == other_t && *(reinterpret_cast<const F*>(this_v)) == *(reinterpret_cast<const F*>(other_v));
-		else
-			return variant_helper<Ts...>::compareEq(this_t, this_v, other_t, other_v);
-	}
-
 	inline static void print(ostream& out, const size_t id, const void* data) {
 		if (id == typeid(F).hash_code())
 			out << *reinterpret_cast<const F*>(data);
@@ -83,27 +76,26 @@ struct variant_helper<F, Ts...> {
 			return variant_helper<Ts...>::string(id, data);
 	}
 
-	inline static bool compareLess(size_t this_t, const void * this_v, size_t other_t, const void * other_v)
+	inline static int compareHelper(size_t this_t, const void * this_v, size_t other_t, const void * other_v)
 	{
-		if (this_t == typeid(F).hash_code() && other_t != typeid(F).hash_code()) return true;
-		if (this_t != typeid(F).hash_code() && other_t == typeid(F).hash_code()) return false;
+		if (this_t == typeid(F).hash_code() && other_t != typeid(F).hash_code()) return -1;
+		if (this_t != typeid(F).hash_code() && other_t == typeid(F).hash_code()) return 1;
 
-		if (this_t == typeid(F).hash_code() && other_t == typeid(F).hash_code())
-			return *(reinterpret_cast<const F*>(this_v)) < *(reinterpret_cast<const F*>(other_v));
-		else
-			return variant_helper<Ts...>::compareLess(this_t, this_v, other_t, other_v);
+		if (this_t == typeid(F).hash_code() && other_t == typeid(F).hash_code()) {
+			compare<F> comp;
+			return comp( *(reinterpret_cast<const F*>(this_v)), *(reinterpret_cast<const F*>(other_v)));
+		} else
+			return variant_helper<Ts...>::compareHelper(this_t, this_v, other_t, other_v);
 	}
-
 };
 
 template<> struct variant_helper<>  {
 inline static void destroy(size_t, void *) { }
 inline static void copy(size_t, const void *, void *) { }
 inline static void move(size_t, void *, void *) { }
-inline static bool compareEq(size_t, const void *, size_t, const void *) { return true; }
 inline static void print(ostream&, const size_t, const void *) {}
 inline static std::string string(const size_t, const void *) { return ""; }
-inline static bool compareLess(size_t, const void *, size_t, const void *) { return false; }
+inline static int compareHelper(size_t, const void *, size_t, const void *) { return 0; }
 };
 
 template<typename ST, typename AT, typename... Ts>
@@ -134,29 +126,29 @@ public:
 	variant_base(F&& value) { this->type_id = typeid(F).hash_code(); new (&this->data) F(std::move(value)); }
 };
 
-template<typename F, typename... Ts>
-class variant : public variant_base<static_max<sizeof(F), sizeof(Ts)...>, static_max<alignof(F), alignof(Ts)...>, F, Ts...> {
-	using helper_t = variant_helper<F, Ts...>;
+template<typename ... Ts>
+class variant : public variant_base<static_max<sizeof(Ts)...>, static_max<alignof(Ts)...>, Ts...> {
+	using helper_t = variant_helper<Ts...>;
 
 public:
-	using variant_base<static_max<sizeof(F), sizeof(Ts)...>, static_max<alignof(F), alignof(Ts)...>, F, Ts...>::variant_base;
+	using variant_base<static_max<sizeof(Ts)...>, static_max<alignof(Ts)...>, Ts...>::variant_base;
 
 	//copy consructor
-	variant(const variant<F, Ts...>& old) : variant_base<static_max<sizeof(F), sizeof(Ts)...>, static_max<alignof(F), alignof(Ts)...>, F, Ts...>()
+	variant(const variant<Ts...>& old) : variant_base<static_max<sizeof(Ts)...>, static_max<alignof(Ts)...>, Ts...>()
 	{
 		this->type_id = old.type_id;
 		helper_t::copy(old.type_id, &old.data, &this->data);
 	}
 
 	//move constructor
-	variant(variant<F, Ts...>&& old) : variant_base<static_max<sizeof(F), sizeof(Ts)...>, static_max<alignof(F), alignof(Ts)...>, F, Ts...>()
+	variant(variant<Ts...>&& old) : variant_base<static_max<sizeof(Ts)...>, static_max<alignof(Ts)...>, Ts...>()
 	{
 		this->type_id = old.type_id;
 		helper_t::move(old.type_id, &old.data, &this->data);
 	}
 
 	//assignment operator
-	variant<F, Ts...>& operator= (variant<F, Ts...> old)
+	variant<Ts...>& operator= (variant<Ts...> old)
 	{
 		std::swap(this->type_id, old.type_id);
 		std::swap(this->data, old.data);
@@ -165,36 +157,41 @@ public:
 	}
 
 
-	bool operator== (const variant<F, Ts...>& other) const
+	bool operator== (const variant<Ts...>& other) const
 	{
-		return helper_t::compareEq(this->type_id, &this->data, other.type_id, &other.data);
+		return helper_t::compareHelper(this->type_id, &this->data, other.type_id, &other.data) == 0;
 	}
 
-	bool operator!= (const variant<F, Ts...>& other) const
+	bool operator!= (const variant<Ts...>& other) const
 	{
 		return !(*this == other);
 	}
 
-	bool operator< (const variant<F, Ts...>& other) const
+	bool operator< (const variant<Ts...>& other) const
 	{
-		return helper_t::compareLess(this->type_id, &this->data, other.type_id, &other.data);
+		return helper_t::compareHelper(this->type_id, &this->data, other.type_id, &other.data) < 0;
 	}
 
-	bool operator> (const variant<F, Ts...>& other) const
+	bool operator> (const variant<Ts...>& other) const
 	{
 		return other < *this;
 	}
 
-	bool operator<= (const variant<F, Ts...>& other) const
+	bool operator<= (const variant<Ts...>& other) const
 	{
 		return !(*this > other);
 	}
 
-	bool operator>= (const variant<F, Ts...>& other) const
+	bool operator>= (const variant<Ts...>& other) const
 	{
 		return !(*this < other);
 	}
 
+	int compare(const variant<Ts...>& other) const
+	{
+		return helper_t::compareHelper(this->type_id, &this->data, other.type_id, &other.data);
+	}
+
 	template<typename T>
 	bool is() const {
 		return (this->type_id == typeid(T).hash_code());
@@ -203,7 +200,7 @@ public:
 	template<typename T>
 	void set(T&& value)
 	{
-		if(std::is_base_of_any<T, F, Ts...>::value) {
+		if(std::is_base_of_any<T, Ts...>::value) {
 			helper_t::destroy(this->type_id, &this->data);
 			new (&this->data) T(value);
 			this->type_id = typeid(T).hash_code();
@@ -214,7 +211,7 @@ public:
 	template<typename T>
 	void set(const T& value)
 	{
-		if(std::is_base_of_any<T, F, Ts...>::value) {
+		if(std::is_base_of_any<T, Ts...>::value) {
 			helper_t::destroy(this->type_id, &this->data);
 			new (&this->data) T(std::move(value));
 			this->type_id = typeid(T).hash_code();
@@ -246,7 +243,7 @@ public:
 		helper_t::destroy(this->type_id, &this->data);
 	}
 
-	friend std::ostream& operator <<(std::ostream& out, const variant<F, Ts...>& obj) {
+	friend std::ostream& operator <<(std::ostream& out, const variant<Ts...>& obj) {
 		helper_t::print(out, obj.type_id, &obj.data);
 		return out;
 	}
@@ -256,6 +253,13 @@ public:
 	}
 };
 
+template<typename ... Ts>
+struct compare<variant<Ts...>> {
+	int operator()(const variant<Ts...>& first, const variant<Ts...>& second) {
+		return first.compare(second);
+	}
+};
+
 } /* namespace std */
 
 #endif
diff --git a/alib2data/src/std/visitor.hpp b/alib2data/src/std/visitor.hpp
index fbce28470437710b6048e80c77c5c82652d8edf0..2dcba5923dc87237e5c472ef781fcdf8ee8e7938 100644
--- a/alib2data/src/std/visitor.hpp
+++ b/alib2data/src/std/visitor.hpp
@@ -61,28 +61,52 @@ class const_promoting_helper;
 template<typename Tested, typename... Other>
 struct const_promoting_helper<Tested, Other...> {
 
+	// variant 1 is swaping first and second argument because it came swaped
 	template<class Desired, class Base, class TargetVisitor,
 			typename std::enable_if< std::is_constructible<Desired, Tested>::value >::type* = nullptr >
-	inline static bool tryPromote(void* userData, const Desired& first, const Base& second, const TargetVisitor& visitor) {
+	inline static bool tryPromote1(void* userData, const Desired& first, const Base& second, const TargetVisitor& visitor) {
+		if(dynamic_cast<const Tested*>(&second)) {
+		//if(Tested::template typeId<Tested>() == second.selfTypeId()) { //TODO on g++-4.9 uncomment
+			visitor.Visit(userData, Desired(static_cast<const Tested&>(second)), first);
+			return true;
+		} else {
+			return const_promoting_helper<Other...>::tryPromote1(userData, first, second, visitor);
+		}
+	}
+
+	template<class Desired, class Base, class TargetVisitor,
+			typename std::enable_if< ! std::is_constructible<Desired, Tested>::value >::type* = nullptr >
+	inline static bool tryPromote1(void* userData, const Desired& first, const Base& second, const TargetVisitor& visitor) {
+		return const_promoting_helper<Other...>::tryPromote1(userData, first, second, visitor);
+	}
+
+	// variant 2 is not swaping first and second argument because it did not came swaped
+	template<class Desired, class Base, class TargetVisitor,
+			typename std::enable_if< std::is_constructible<Desired, Tested>::value >::type* = nullptr >
+	inline static bool tryPromote2(void* userData, const Desired& first, const Base& second, const TargetVisitor& visitor) {
 		if(dynamic_cast<const Tested*>(&second)) {
 		//if(Tested::template typeId<Tested>() == second.selfTypeId()) { //TODO on g++-4.9 uncomment
 			visitor.Visit(userData, first, Desired(static_cast<const Tested&>(second)));
 			return true;
 		} else {
-			return const_promoting_helper<Other...>::tryPromote(userData, first, second, visitor);
+			return const_promoting_helper<Other...>::tryPromote2(userData, first, second, visitor);
 		}
 	}
 
 	template<class Desired, class Base, class TargetVisitor,
 			typename std::enable_if< ! std::is_constructible<Desired, Tested>::value >::type* = nullptr >
-	inline static bool tryPromote(void* userData, const Desired& first, const Base& second, const TargetVisitor& visitor) {
-		return const_promoting_helper<Other...>::tryPromote(userData, first, second, visitor);
+	inline static bool tryPromote2(void* userData, const Desired& first, const Base& second, const TargetVisitor& visitor) {
+		return const_promoting_helper<Other...>::tryPromote2(userData, first, second, visitor);
 	}
 };
 
 template<> struct const_promoting_helper<>  {
+
+	template<class Desired, class Base, class TargetVisitor>
+	inline static bool tryPromote1(void*, const Desired&, const Base&, const TargetVisitor&) { return false; }
+
 	template<class Desired, class Base, class TargetVisitor>
-	inline static bool tryPromote(void*, const Desired&, const Base&, const TargetVisitor&) { return false; }
+	inline static bool tryPromote2(void*, const Desired&, const Base&, const TargetVisitor&) { return false; }
 };
 
 class const_promoting_visitor_base {};
@@ -97,14 +121,27 @@ class const_promoting_visitor<T> : public const_promoting_visitor_base {
 public:
 	virtual void Visit(void*, const T &, const T&) const = 0;
 
+	// variant 1 is swaping first and second argument because it came swaped
 	template<typename R, typename promoting_helper_type>
 	bool Visit1(void* userData, const T& first, const R& second) const {
+		if(dynamic_cast<const T*>(&second)) {
+		//if(T::template typeId<T>() == second.selfTypeId()) { //TODO on g++-4.9 uncomment
+			this->Visit(userData, static_cast<const T&>(second), first);
+			return true;
+		} else {
+			return promoting_helper_type::tryPromote1( userData, first, second, *this );
+		}
+	}
+
+	// variant 2 is not swaping first and second argument because it did not came swaped
+	template<typename R, typename promoting_helper_type>
+	bool Visit2(void* userData, const T& first, const R& second) const {
 		if(dynamic_cast<const T*>(&second)) {
 		//if(T::template typeId<T>() == second.selfTypeId()) { //TODO on g++-4.9 uncomment
 			this->Visit(userData, first, static_cast<const T&>(second));
 			return true;
 		} else {
-			return promoting_helper_type::tryPromote( userData, first, second, *this );
+			return promoting_helper_type::tryPromote2( userData, first, second, *this );
 		}
 	}
 };
@@ -116,17 +153,31 @@ public:
 	// promote the function(s) from the base class
 	using const_promoting_visitor<Types...>::Visit;
 	using const_promoting_visitor<Types...>::Visit1;
+	using const_promoting_visitor<Types...>::Visit2;
 
 	virtual void Visit(void*, const T &, const T&) const = 0;
 
+	// variant 1 is swaping first and second argument because it came swaped
 	template<typename R, typename promoting_helper_type>
 	bool Visit1(void* userData, const T& first, const R& second) const {
+		if(dynamic_cast<const T*>(&second)) {
+		//if(T::template typeId<T>() == second.selfTypeId()) { //TODO on g++-4.9 uncomment
+			this->Visit(userData, static_cast<const T&>(second), first);
+			return true;
+		} else {
+			return promoting_helper_type::tryPromote1( userData, first, second, *this );
+		}
+	}
+
+	// variant 2 is not swaping first and second argument because it did not came swaped
+	template<typename R, typename promoting_helper_type>
+	bool Visit2(void* userData, const T& first, const R& second) const {
 		if(dynamic_cast<const T*>(&second)) {
 		//if(T::template typeId<T>() == second.selfTypeId()) { //TODO on g++-4.9 uncomment
 			this->Visit(userData, first, static_cast<const T&>(second));
 			return true;
 		} else {
-			return promoting_helper_type::tryPromote( userData, first, second, *this );
+			return promoting_helper_type::tryPromote2( userData, first, second, *this );
 		}
 	}
 };
@@ -194,7 +245,7 @@ public:
 
 	virtual void Accept(void* userData, const const_visitor<Types...>& visitor) const = 0;
 
-	virtual bool Accept(void* userData, const T& other, const const_promoting_visitor<Types...>& visitor) const = 0;
+	virtual bool Accept(void* userData, const T& other, const const_promoting_visitor<Types...>& visitor, bool swap) const = 0;
 
 	virtual void Accept(void* userData, const T& other, const const_same_visitor<Types...>& visitor) const = 0;
 };
@@ -210,8 +261,14 @@ public:
 		visitor.Visit(userData, static_cast<const Derived&>(*this));
 	}
 
-	virtual bool Accept(void* userData, const typename AcceptorBase::base_type& other, const typename AcceptorBase::const_promoting_visitor_type& visitor) const {
-		return visitor.template Visit1<typename AcceptorBase::base_type, typename AcceptorBase::const_promoting_helper_type>(userData, static_cast<const Derived&>(*this), other);
+	virtual bool Accept(void* userData, const typename AcceptorBase::base_type& other, const typename AcceptorBase::const_promoting_visitor_type& visitor, bool swap) const {
+		if(swap) {
+			// variant 1 is swaping first and second argument because it came swaped
+			return visitor.template Visit1<typename AcceptorBase::base_type, typename AcceptorBase::const_promoting_helper_type>(userData, static_cast<const Derived&>(*this), other);
+		} else {
+			// variant 2 is not swaping first and second argument because it did not came swaped
+			return visitor.template Visit2<typename AcceptorBase::base_type, typename AcceptorBase::const_promoting_helper_type>(userData, static_cast<const Derived&>(*this), other);
+		}
 	}
 
 	virtual void Accept(void* userData, const typename AcceptorBase::base_type& other, const typename AcceptorBase::const_same_visitor_type& visitor) const {
@@ -229,10 +286,12 @@ template<class T, class R,
 		typename std::enable_if< std::is_base_of< const_promoting_visitor_base, R >::value >::type* = nullptr >
 void Accept(void* userData, const T& first, const T& second, const R& visitor) {
 	bool res;
-	res = first.Accept(userData, second, visitor);
+	// variant 2 is swaping first and second argument because it come swaped
+	res = first.Accept(userData, second, visitor, false);
 	if(res) return;
 
-	res = second.Accept(userData, first, visitor);
+	// variant 1 is not swaping first and second argument because it did not come swaped
+	res = second.Accept(userData, first, visitor, true);
 	if(res) return;
 
 	throw std::logic_error("Promoting visitor: Can't promote one parameter to type of the other.");
diff --git a/alib2data/test-src/std/StdTest.h b/alib2data/test-src/std/StdTest.h
index cfd048cc5b8edc5f9253018a042e4781f19eb88b..20f727dd4c8f72074f1ba6d3cf69461439f9cda5 100644
--- a/alib2data/test-src/std/StdTest.h
+++ b/alib2data/test-src/std/StdTest.h
@@ -2,6 +2,7 @@
 #define VARIANT_TEST_H_
 
 #include <cppunit/extensions/HelperMacros.h>
+#include "std/compare.hpp"
 
 class StdTest : public CppUnit::TestFixture
 {
@@ -11,6 +12,7 @@ class StdTest : public CppUnit::TestFixture
   CPPUNIT_TEST( testVariantSet );
   CPPUNIT_TEST_SUITE_END();
 
+public:
 struct test {
 	int * holder;
 
@@ -43,6 +45,10 @@ struct test {
 		return *(this->holder) == *(other.holder);
 	}
 
+	int compare(const test& other) const {
+		return *(this->holder) - *(other.holder);
+	}
+
 	friend std::ostream& operator<<(std::ostream& out, const test& other) {
 		out << *(other.holder);
 		return out;
@@ -64,4 +70,15 @@ public:
   void testVariantSet();
 };
 
+namespace std {
+
+template<>
+struct compare<StdTest::test> {
+	int operator()(const StdTest::test& first, const StdTest::test& second) {
+		return first.compare(second);
+	}
+};
+
+} /* namespace std */
+
 #endif  // VARIANT_TEST_H_
diff --git a/alib2data/test-src/std/StdVisitorTest.cpp b/alib2data/test-src/std/StdVisitorTest.cpp
index 2d275a47fbbca1278d61413e8093ee759aedec36..8496191a404c40d78710a0681f0d0b5945ebc5cd 100644
--- a/alib2data/test-src/std/StdVisitorTest.cpp
+++ b/alib2data/test-src/std/StdVisitorTest.cpp
@@ -206,20 +206,20 @@ class TmpSameVisitor : public VisitableTmpBase::const_same_visitor_type {
 
 class TmpPromotingVisitor : public VisitableTmpBase::const_promoting_visitor_type {
 	void Visit(void* userData, const Tmp1& first, const Tmp1& second) const {
-		int& data = *((int*) userData);
-		data = 1;
+		std::string& data = *((std::string*) userData);
+		data = std::to_string(first.getData()) + " " + std::to_string(second.getData());
 		std::cout << first << " " << second << std::endl;
 	}
 
 	void Visit(void* userData, const Tmp2& first, const Tmp2& second) const {
-		int& data = *((int*) userData);
-		data = 2;
+		std::string& data = *((std::string*) userData);
+		data = std::to_string(first.getData()) + " " + std::to_string(second.getData());
 		std::cout << first << " " << second << std::endl;
 	}
 
 	void Visit(void* userData, const Tmp3& first, const Tmp3& second) const {
-		int& data = *((int*) userData);
-		data = 3;
+		std::string& data = *((std::string*) userData);
+		data = first.getData() + " " + second.getData();
 		std::cout << first << " " << second << std::endl;
 	}
 };
@@ -249,11 +249,16 @@ void StdVisitorTest::testSameVisitor() {
 void StdVisitorTest::testPromoteVisitor() {
 	TmpPromotingVisitor visitor;
 
-	Tmp1 tmp1(2);
+	Tmp1 tmp1(1);
 	Tmp3 tmp3("3");
 
-	int a = 0;
+	std::string a = "";
 	Accept((void*) &a, (TmpBase&) tmp1, (TmpBase&) tmp3, visitor);
 
-	CPPUNIT_ASSERT(a == 3);
+	CPPUNIT_ASSERT(a == "1 3");
+
+	std::string b = "";
+	Accept((void*) &b, (TmpBase&) tmp3, (TmpBase&) tmp1, visitor);
+
+	CPPUNIT_ASSERT(b == "3 1");
 }