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"); }