From c9085dd32437b38d8121ce5073673ee434ab9244 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Sat, 14 May 2016 14:04:05 +0200
Subject: [PATCH] refactor alib2std compare

---
 alib2std/src/extensions/compare.hpp          | 10 ++++++++++
 alib2std/src/extensions/deque.hpp            | 12 ++++++------
 alib2std/src/extensions/list.hpp             | 12 ++++++------
 alib2std/src/extensions/map.hpp              | 12 ++++++------
 alib2std/src/extensions/pair.hpp             |  4 ++--
 alib2std/src/extensions/set.hpp              | 12 ++++++------
 alib2std/src/extensions/unordered_map.hpp    | 12 ++++++------
 alib2std/src/extensions/variant.hpp          |  2 +-
 alib2std/src/extensions/vector.hpp           | 12 ++++++------
 alib2std/test-src/extensions/CompareTest.cpp | 17 +++++++++++++++++
 10 files changed, 66 insertions(+), 39 deletions(-)

diff --git a/alib2std/src/extensions/compare.hpp b/alib2std/src/extensions/compare.hpp
index 071b7a7578..f92be80ef7 100644
--- a/alib2std/src/extensions/compare.hpp
+++ b/alib2std/src/extensions/compare.hpp
@@ -8,6 +8,8 @@
 #ifndef COMPARE_HPP_
 #define COMPARE_HPP_
 
+#include <utility>
+
 namespace std {
 
 template < typename T, typename Enable = void >
@@ -34,6 +36,14 @@ struct compare<double> {
 	}
 };
 
+template<class T>
+struct compare<T*> {
+	int operator()( T * const & first, T * const & second) const {
+		compare<typename std::decay < T >::type > comp;
+		return comp(*first, *second);
+	}
+};
+
 } /* namespace std */
 
 #endif /* COMPARE_HPP_ */
diff --git a/alib2std/src/extensions/deque.hpp b/alib2std/src/extensions/deque.hpp
index 87fe60a448..c2ac58f5b7 100644
--- a/alib2std/src/extensions/deque.hpp
+++ b/alib2std/src/extensions/deque.hpp
@@ -10,8 +10,8 @@
 
 namespace std {
 
-template < class T >
-std::ostream & operator <<( std::ostream & out, const std::deque < T > & list ) {
+template < class T, class ... Ts >
+std::ostream & operator <<( std::ostream & out, const std::deque < T, Ts ... > & list ) {
 	out << "[";
 
 	bool first = true;
@@ -27,14 +27,14 @@ std::ostream & operator <<( std::ostream & out, const std::deque < T > & list )
 	return out;
 }
 
-template < class T >
-struct compare < deque < T > > {
-	int operator ()( const deque < T > & first, const deque < T > & second ) const {
+template < class T, class ... Ts >
+struct compare < deque < T, Ts ... > > {
+	int operator ()( const deque < T, Ts ... > & first, const deque < T, Ts ... > & second ) const {
 		if ( first.size ( ) < second.size ( ) ) return -1;
 
 		if ( first.size ( ) > second.size ( ) ) return 1;
 
-		compare < T > comp;
+		compare < typename std::decay < T >::type > comp;
 
 		for ( auto iterF = first.begin ( ), iterS = second.begin ( ); iterF != first.end ( ); ++iterF, ++iterS ) {
 			int res = comp ( * iterF, * iterS );
diff --git a/alib2std/src/extensions/list.hpp b/alib2std/src/extensions/list.hpp
index 65fe68e730..6dc9a317f9 100644
--- a/alib2std/src/extensions/list.hpp
+++ b/alib2std/src/extensions/list.hpp
@@ -10,8 +10,8 @@
 
 namespace std {
 
-template< class T >
-std::ostream& operator<<(std::ostream& out, const std::list<T>& list) {
+template< class T, class ... Ts >
+std::ostream& operator<<(std::ostream& out, const std::list<T, Ts ... >& list) {
 	out << "[";
 
 	bool first = true;
@@ -25,13 +25,13 @@ std::ostream& operator<<(std::ostream& out, const std::list<T>& list) {
 	return out;
 }
 
-template<class T>
-struct compare<list<T>> {
-	int operator()(const list<T>& first, const list<T>& second) const {
+template<class T, class ... Ts >
+struct compare<list<T, Ts ... >> {
+	int operator()(const list<T, Ts ... >& first, const list<T, Ts ... >& second) const {
 		if(first.size() < second.size()) return -1;
 		if(first.size() > second.size()) return 1;
 
-		compare<T> comp;
+		compare<typename std::decay < T >::type > comp;
 		for(auto iterF = first.begin(), iterS = second.begin(); iterF != first.end(); ++iterF, ++iterS) {
 			int res = comp(*iterF, *iterS);
 			if(res != 0) return res;
diff --git a/alib2std/src/extensions/map.hpp b/alib2std/src/extensions/map.hpp
index 1d8bb3219e..b2d0f16739 100644
--- a/alib2std/src/extensions/map.hpp
+++ b/alib2std/src/extensions/map.hpp
@@ -12,8 +12,8 @@
 
 namespace std {
 
-template< class T, class R >
-std::ostream& operator<<(std::ostream& out, const std::map<T, R>& map) {
+template< class T, class R, class ... Ts >
+std::ostream& operator<<(std::ostream& out, const std::map<T, R, Ts ... >& map) {
 	out << "{";
 
 	bool first = true;
@@ -27,13 +27,13 @@ std::ostream& operator<<(std::ostream& out, const std::map<T, R>& map) {
 	return out;
 }
 
-template<class T, class R>
-struct compare<map<T, R>> {
-	int operator()(const map<T, R>& first, const map<T, R>& second) const {
+template<class T, class R, class ... Ts>
+struct compare<map<T, R, Ts ...>> {
+	int operator()(const map<T, R, Ts ...>& first, const map<T, R, Ts ...>& second) const {
 		if(first.size() < second.size()) return -1;
 		if(first.size() > second.size()) return 1;
 
-		compare<std::pair<T, R>> comp;
+		compare<std::pair<typename std::decay < T >::type, typename std::decay < R >::type >> comp;
 		for(auto iterF = first.begin(), iterS = second.begin(); iterF != first.end(); ++iterF, ++iterS) {
 			int res = comp(*iterF, *iterS);
 			if(res != 0) return res;
diff --git a/alib2std/src/extensions/pair.hpp b/alib2std/src/extensions/pair.hpp
index a6dae53526..dcf11667e5 100644
--- a/alib2std/src/extensions/pair.hpp
+++ b/alib2std/src/extensions/pair.hpp
@@ -19,8 +19,8 @@ std::ostream& operator<<(std::ostream& out, const std::pair<T, R>& pair) {
 template<class T, class R>
 struct compare<pair<T, R>> {
 	int operator()(const pair<T, R>& first, const pair<T, R>& second) const {
-		compare<T> compT;
-		compare<R> compR;
+		compare<typename std::decay < T >::type > compT;
+		compare<typename std::decay < R >::type > compR;
 
 		int res = compT(first.first, second.first);
 		if(res == 0) res = compR(first.second, second.second);
diff --git a/alib2std/src/extensions/set.hpp b/alib2std/src/extensions/set.hpp
index 3d1f639e96..ab34e6d25e 100644
--- a/alib2std/src/extensions/set.hpp
+++ b/alib2std/src/extensions/set.hpp
@@ -10,8 +10,8 @@
 
 namespace std {
 
-template< class T >
-std::ostream& operator<<(std::ostream& out, const std::set<T>& list) {
+template< class T, class ... Ts >
+std::ostream& operator<<(std::ostream& out, const std::set<T, Ts ...>& list) {
 	out << "{";
 
 	bool first = true;
@@ -25,13 +25,13 @@ std::ostream& operator<<(std::ostream& out, const std::set<T>& list) {
 	return out;
 }
 
-template<class T>
-struct compare<set<T>> {
-	int operator()(const set<T>& first, const set<T>& second) const {
+template<class T, class ... Ts>
+struct compare<set<T, Ts ...>> {
+	int operator()(const set<T, Ts ...>& first, const set<T, Ts ...>& second) const {
 		if(first.size() < second.size()) return -1;
 		if(first.size() > second.size()) return 1;
 
-		compare<T> comp;
+		compare<typename std::decay < T >::type > comp;
 		for(auto iterF = first.begin(), iterS = second.begin(); iterF != first.end(); ++iterF, ++iterS) {
 			int res = comp(*iterF, *iterS);
 			if(res != 0) return res;
diff --git a/alib2std/src/extensions/unordered_map.hpp b/alib2std/src/extensions/unordered_map.hpp
index 9c075beb57..97d722dee4 100644
--- a/alib2std/src/extensions/unordered_map.hpp
+++ b/alib2std/src/extensions/unordered_map.hpp
@@ -10,8 +10,8 @@
 
 namespace std {
 
-template< class T, class R >
-std::ostream& operator<<(std::ostream& out, const std::unordered_map<T, R>& map) {
+template< class T, class R, class ... Ts >
+std::ostream& operator<<(std::ostream& out, const std::unordered_map<T, R, Ts ... >& map) {
 	out << "{";
 
 	bool first = true;
@@ -25,13 +25,13 @@ std::ostream& operator<<(std::ostream& out, const std::unordered_map<T, R>& map)
 	return out;
 }
 
-template<class T, class R>
-struct compare<unordered_map<T, R>> {
-	int operator()(const unordered_map<T, R>& first, const unordered_map<T, R>& second) const {
+template<class T, class R, class ... Ts>
+struct compare<unordered_map<T, R, Ts ...>> {
+	int operator()(const unordered_map<T, R, Ts ...>& first, const unordered_map<T, R, Ts ...>& second) const {
 		if(first.size() < second.size()) return -1;
 		if(first.size() > second.size()) return 1;
 
-		compare<R> comp;
+		compare<typename std::decay < R >::type > comp;
 		for(auto iter = first.begin(); iter != first.end(); ++iter) {
 			auto search = second.find(iter->first);
 			if(search == second.end()) return -1;
diff --git a/alib2std/src/extensions/variant.hpp b/alib2std/src/extensions/variant.hpp
index 7d5dc25a29..052d79b506 100644
--- a/alib2std/src/extensions/variant.hpp
+++ b/alib2std/src/extensions/variant.hpp
@@ -83,7 +83,7 @@ struct variant_helper<F, Ts...> {
 		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()) {
-			compare<F> comp;
+			compare<typename std::decay < F >::type > 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);
diff --git a/alib2std/src/extensions/vector.hpp b/alib2std/src/extensions/vector.hpp
index 7efeaba3f7..db96b78886 100644
--- a/alib2std/src/extensions/vector.hpp
+++ b/alib2std/src/extensions/vector.hpp
@@ -10,8 +10,8 @@
 
 namespace std {
 
-template< class T , class Allocator >
-std::ostream& operator<<(std::ostream& out, const std::vector<T, Allocator>& vector) {
+template< class T , class ... Ts >
+std::ostream& operator<<(std::ostream& out, const std::vector<T, Ts ...>& vector) {
 	out << "[";
 
 	bool first = true;
@@ -25,13 +25,13 @@ std::ostream& operator<<(std::ostream& out, const std::vector<T, Allocator>& vec
 	return out;
 }
 
-template<class T, class Allocator>
-struct compare<vector<T, Allocator>> {
-	int operator()(const vector<T, Allocator>& first, const vector<T, Allocator>& second) const {
+template<class T, class ... Ts>
+struct compare<vector<T, Ts ...>> {
+	int operator()(const vector<T, Ts...>& first, const vector<T, Ts...>& second) const {
 		if(first.size() < second.size()) return -1;
 		if(first.size() > second.size()) return 1;
 
-		compare<T> comp;
+		compare<typename std::decay < T >::type > comp;
 		for(auto iterF = first.begin(), iterS = second.begin(); iterF != first.end(); ++iterF, ++iterS) {
 			int res = comp(*iterF, *iterS);
 			if(res != 0) return res;
diff --git a/alib2std/test-src/extensions/CompareTest.cpp b/alib2std/test-src/extensions/CompareTest.cpp
index 014405b436..7f91019f86 100644
--- a/alib2std/test-src/extensions/CompareTest.cpp
+++ b/alib2std/test-src/extensions/CompareTest.cpp
@@ -2,6 +2,7 @@
 #include <set>
 #include <vector>
 #include <pair>
+#include <map>
 
 
 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( CompareTest, "bits" );
@@ -31,5 +32,21 @@ void CompareTest::testCompare() {
 
 	std::compare<std::pair<std::set<std::vector<int>>, std::set<std::vector<int>>>> comp3;
 	CPPUNIT_ASSERT(comp3(pair1, pair2) < 0);
+
+	int two = 2;
+	int three = 3;
+	int four = 4;
+
+	std::map<int, const int*> map1 = { {1, &two}, {2, &three} };
+	std::map<int, const int*> map2 = { {2, &three}, {3, &four} };
+
+	std::compare<std::map<int, const int*>> comp4;
+	CPPUNIT_ASSERT(comp4(map1, map2) < 0);
+
+	auto first = std::tie(vector1, set1, pair1, map1);
+	auto second = std::tie(vector2, set2, pair2, map2);
+
+	std::compare<decltype ( first ) > comp5;
+	CPPUNIT_ASSERT(comp5(first, second) < 0);
 }
 
-- 
GitLab