From 9205bb97c3a4d6b454660124702eb8426d7f18ea Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Fri, 20 Apr 2018 14:22:34 +0200
Subject: [PATCH] update tuple std extension

---
 alib2std/src/extensions/tuple.hpp          | 81 +++++++++++-----------
 alib2std/test-src/extensions/TupleTest.cpp |  6 ++
 2 files changed, 48 insertions(+), 39 deletions(-)

diff --git a/alib2std/src/extensions/tuple.hpp b/alib2std/src/extensions/tuple.hpp
index ee11bca9c7..dd3d748666 100644
--- a/alib2std/src/extensions/tuple.hpp
+++ b/alib2std/src/extensions/tuple.hpp
@@ -58,6 +58,12 @@ class tuple_size;
 template < class ... Types >
 class tuple_size < ext::tuple < Types ... > > : public std::integral_constant < std::size_t, sizeof...( Types ) > { };
 
+template < class T >
+class tuple_size < T & > : public std::integral_constant < std::size_t, ext::tuple_size < T >::value > { };
+
+template < class T >
+class tuple_size < T && > : public std::integral_constant < std::size_t, ext::tuple_size < T >::value > { };
+
 template < class T >
 class tuple_size < const T > : public std::integral_constant < std::size_t, ext::tuple_size < T >::value > { };
 
@@ -94,26 +100,28 @@ struct tuple_element < I, const volatile T > {
 template < class Result, unsigned I, class Tuple, class Callable >
 struct call_on_nth_helper;
 
-template < class Result, unsigned I, class Tuple, class Callable >
-struct call_on_nth_helper {
-	static Result call_on_nth_fn ( Tuple & t, unsigned index, Callable callback ) {
+template < class Result, unsigned I, class Callable, class ... Types >
+struct call_on_nth_helper < Result, I, ext::tuple < Types ... >, Callable > {
+	template < class Tuple >
+	static Result call_on_nth_fn ( Tuple && t, unsigned index, Callable callback ) {
 		if ( index == 0 )
-			return callback ( std::get < ext::tuple_size < Tuple >::value - I > ( t ) );
+			return callback ( std::get < ext::tuple_size < Tuple >::value - I > ( std::forward < Tuple && > ( t ) ) );
 		else
-			return call_on_nth_helper < Result, I - 1, Tuple, Callable >::call_on_nth_fn ( t, index - 1, callback );
+			return call_on_nth_helper < Result, I - 1, ext::tuple < Types ... >, Callable >::call_on_nth_fn ( std::forward < Tuple && > ( t ), index - 1, callback );
 	}
 };
 
-template < class Result, class Tuple, class Callable >
-struct call_on_nth_helper < Result, 0, Tuple, Callable > {
-	static Result call_on_nth_fn ( Tuple &, unsigned, Callable ) {
+template < class Result, class Callable, class ... Types >
+struct call_on_nth_helper < Result, 0, ext::tuple < Types ... >, Callable > {
+	template < class Tuple >
+	static Result call_on_nth_fn ( Tuple &&, unsigned, Callable ) {
 		throw std::out_of_range ( "Not enough elements in tuple." );
 	}
 };
 
 template < class Result, class Tuple, class Callable >
-Result call_on_nth ( Tuple & t, unsigned index, Callable callback ) {
-	return call_on_nth_helper < Result, ext::tuple_size < Tuple >::value, Tuple, Callable >::call_on_nth_fn ( t, index, callback );
+Result call_on_nth ( Tuple && t, unsigned index, Callable callback ) {
+	return call_on_nth_helper < Result, ext::tuple_size < Tuple >::value, typename std::decay < Tuple >::type, Callable >::call_on_nth_fn ( std::forward < Tuple && > ( t ), index, callback );
 }
 
 
@@ -121,23 +129,25 @@ Result call_on_nth ( Tuple & t, unsigned index, Callable callback ) {
 template < unsigned I, class Tuple, class Callable >
 struct foreach_helper;
 
-template < unsigned I, class Tuple, class Callable >
-struct foreach_helper {
-	static void foreach_fn ( Tuple & t, Callable callback ) {
+template < unsigned I, class Callable, class ... Types >
+struct foreach_helper < I, ext::tuple < Types ... >, Callable > {
+	template < class Tuple >
+	static void foreach_fn ( Tuple && t, Callable callback ) {
+		foreach_helper < I - 1, ext::tuple < Types ... >, Callable >::foreach_fn ( std::forward < Tuple && > ( t ), callback );
 		callback ( std::get < I - 1 > ( t ) );
-		foreach_helper < I - 1, Tuple, Callable >::foreach_fn ( t, callback );
 	}
 };
 
-template < class Tuple, class Callable >
-struct foreach_helper < 0, Tuple, Callable > {
-	static void foreach_fn ( Tuple &, Callable ) {
+template < class Callable, class ... Types >
+struct foreach_helper < 0, ext::tuple < Types ... >, Callable > {
+	template < class Tuple >
+	static void foreach_fn ( Tuple &&, Callable ) {
 	}
 };
 
 template < class Tuple, class Callable >
-void foreach ( Tuple & t, Callable callback ) {
-	return foreach_helper < ext::tuple_size < Tuple >::value, Tuple, Callable >::foreach_fn ( t, callback );
+void foreach ( Tuple && t, Callable callback ) {
+	return foreach_helper < ext::tuple_size < Tuple >::value, typename std::decay < Tuple >::type, Callable >::foreach_fn ( std::forward < Tuple && > ( t ), callback );
 }
 
 
@@ -146,7 +156,7 @@ template < class Tuple, class Callable >
 bool all_of ( const Tuple & t, Callable callback ) {
 	bool res = true;
 
-	auto aggregateCallback = [ & ] ( auto & arg0 ) {
+	auto aggregateCallback = [ & ] ( const auto & arg0 ) {
 		res &= callback ( arg0 );
 	};
 
@@ -154,28 +164,21 @@ bool all_of ( const Tuple & t, Callable callback ) {
 	return res;
 }
 
-template<int I, class Tuple>
-struct operator_shift_left_impl;
-
-template<int I, class Tuple>
-struct operator_shift_left_impl {
-	static void operator_shift_left ( std::ostream& out, const Tuple& t) {
-		operator_shift_left_impl < I - 1, Tuple>::operator_shift_left ( out, t );
-		out << ", " << std::get < I > ( t );
-	}
-};
-
-template<class Tuple>
-struct operator_shift_left_impl<0, Tuple> {
-	static void operator_shift_left ( std::ostream& out, const Tuple& t) {
-		out << std::get < 0 > ( t );
-	}
-};
-
 template< class... Ts>
 std::ostream& operator<<(std::ostream& out, const ext::tuple<Ts...>& tuple) {
 	out << "(";
-	ext::operator_shift_left_impl < ext::tuple_size < ext::tuple < Ts ... > >::value - 1, ext::tuple < Ts ... > >::operator_shift_left ( out, tuple );
+
+	bool first = true;
+	auto outCallback = [ & ] ( const auto & arg0 ) {
+		if ( ! first ) {
+			out << ", ";
+		} else {
+			first = false;
+		}
+		out << arg0;
+	};
+
+	ext::foreach ( tuple, outCallback  );
 	out << ")";
 	return out;
 }
diff --git a/alib2std/test-src/extensions/TupleTest.cpp b/alib2std/test-src/extensions/TupleTest.cpp
index a57e76968d..89c4c83992 100644
--- a/alib2std/test-src/extensions/TupleTest.cpp
+++ b/alib2std/test-src/extensions/TupleTest.cpp
@@ -1,5 +1,6 @@
 #include "TupleTest.h"
 #include <alib/tuple>
+#include <sstream>
 
 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( TupleTest, "bits" );
 CPPUNIT_TEST_SUITE_REGISTRATION( TupleTest );
@@ -14,5 +15,10 @@ void TupleTest::testCallOnNth() {
 	ext::tuple < int, int, int, int, int > t = ext::make_tuple ( 1, 2, 3, 4, 5 );
 
 	CPPUNIT_ASSERT ( ext::call_on_nth < int > ( t, 1, [] ( int i ) { return i; } ) == 2 );
+
+	std::stringstream ss;
+	ss << t;
+	std::cout << ss.str ( ) << std::endl;
+	CPPUNIT_ASSERT ( ss.str ( ) == "(1, 2, 3, 4, 5)" );
 }
 
-- 
GitLab