Index: src/Common/utility.h
===================================================================
--- src/Common/utility.h	(revision 271a5d3f2973ea004bdf84109ba973738c2bae8a)
+++ src/Common/utility.h	(revision 5ce0659eed1c7e50a124c06d47bf11f898fe01e4)
@@ -452,64 +452,52 @@
 
 // -----------------------------------------------------------------------------
-// Helper struct and function to support
-// for ( val : group_iterate( container1, container2, ... ) ) {}
-// syntax to have a for each that iterates multiple containers of the same length
-// TODO: update to use variadic arguments
-
-template< typename... >
-struct group_iterate_t;
-
-template< typename T1, typename T2 >
-struct group_iterate_t<T1, T2> {
-private:
-	std::tuple<T1, T2> args;
+// Helper struct and function to support:
+// for ( auto val : group_iterate( container1, container2, ... ) ) { ... }
+// This iteraters through multiple containers of the same size.
+
+template<typename... Args>
+class group_iterate_t {
+	using Iterables = std::tuple<Args...>;
+	Iterables iterables;
+
+	template<size_t I> using Iter = decltype(std::get<I>(iterables).begin());
+	template<size_t I> using Data = decltype(*std::get<I>(iterables).begin());
+	template<typename> struct base_iterator;
+
+	template<std::size_t... Is>
+	struct base_iterator<std::integer_sequence<std::size_t, Is...>> {
+		using value_type = std::tuple< Data<Is>... >;
+		std::tuple<Iter<Is>...> iterators;
+
+		base_iterator( Iter<Is>... is ) : iterators( is... ) {}
+		base_iterator operator++() {
+			return base_iterator( ++std::get<Is>( iterators )... );
+		}
+		bool operator!=( const base_iterator& other ) const {
+			return iterators != other.iterators;
+		}
+		value_type operator*() const {
+			return std::tie( *std::get<Is>( iterators )... );
+		}
+
+		static base_iterator make_begin( Iterables & data ) {
+			return base_iterator( std::get<Is>( data ).begin()... );
+		}
+		static base_iterator make_end( Iterables & data ) {
+			return base_iterator( std::get<Is>( data ).end()... );
+		}
+	};
+
 public:
-	group_iterate_t( const T1 & v1, const T2 & v2 ) : args(v1, v2) {};
-
-	typedef std::tuple<decltype(*std::get<0>(args).begin()), decltype(*std::get<1>(args).begin())> value_type;
-	typedef decltype(std::get<0>(args).begin()) T1Iter;
-	typedef decltype(std::get<1>(args).begin()) T2Iter;
-
-	struct iterator {
-		typedef std::tuple<T1Iter, T2Iter> IterTuple;
-		IterTuple it;
-		iterator( T1Iter i1, T2Iter i2 ) : it( i1, i2 ) {}
-		iterator operator++() {
-			return iterator( ++std::get<0>(it), ++std::get<1>(it) );
-		}
-		bool operator!=( const iterator &other ) const { return it != other.it; }
-		value_type operator*() const { return std::tie( *std::get<0>(it), *std::get<1>(it) ); }
-	};
-
-	iterator begin() { return iterator( std::get<0>(args).begin(), std::get<1>(args).begin() ); }
-	iterator end() { return iterator( std::get<0>(args).end(), std::get<1>(args).end() ); }
-};
-
-template< typename T1, typename T2, typename T3 >
-struct group_iterate_t<T1, T2, T3> {
-private:
-	std::tuple<T1, T2, T3> args;
-public:
-	group_iterate_t( const T1 & v1, const T2 & v2, const T3 & v3 ) : args(v1, v2, v3) {};
-
-	template<size_t I> using Iter = decltype(std::get<I>(args).begin());
-	using value_type = std::tuple<decltype(*std::get<0>(args).begin()), decltype(*std::get<1>(args).begin()), decltype(*std::get<2>(args).begin())>;
-
-	struct iterator {
-		typedef std::tuple<Iter<0>, Iter<1>, Iter<2>> IterTuple;
-		IterTuple it;
-		iterator( Iter<0> i0, Iter<1> i1, Iter<2> i2 ) : it( i0, i1, i2 ) {}
-		iterator operator++() {
-			return iterator( ++std::get<0>(it), ++std::get<1>(it), ++std::get<2>(it) );
-		}
-		bool operator!=( const iterator &other ) const { return it != other.it; }
-		value_type operator*() const { return std::tie( *std::get<0>(it), *std::get<1>(it), *std::get<2>(it) ); }
-	};
-
-	iterator begin() { return iterator( std::get<0>(args).begin(), std::get<1>(args).begin(), std::get<2>(args).begin() ); }
-    iterator end() { return iterator( std::get<0>(args).end(), std::get<1>(args).end(), std::get<2>(args).end() ); }
-};
-
-// Helpers for the bounds checks:
+	group_iterate_t( const Args &... args ) : iterables( args... ) {}
+
+	using iterator = base_iterator<decltype(
+		std::make_integer_sequence<std::size_t, sizeof...(Args)>())>;
+
+	iterator begin() { return iterator::make_begin( iterables ); }
+	iterator end() { return iterator::make_end( iterables ); }
+};
+
+// Helpers for the bounds checks (the non-varatic part of group_iterate):
 static inline void runGroupBoundsCheck(size_t size0, size_t size1) {
 	assertf( size0 == size1,
@@ -524,5 +512,5 @@
 }
 
-/// performs bounds check to ensure that all arguments are of the same length.
+/// Performs bounds check to ensure that all arguments are of the same length.
 template< typename... Args >
 group_iterate_t<Args...> group_iterate( Args &&... args ) {
@@ -531,5 +519,5 @@
 }
 
-/// does not perform a bounds check - requires user to ensure that iteration terminates when appropriate.
+/// Does not perform a bounds check - requires user to ensure that iteration terminates when appropriate.
 template< typename... Args >
 group_iterate_t<Args...> unsafe_group_iterate( Args &&... args ) {
