#include <vector>
#include <tuple>
#include <string>
#include <iostream>
// BORROWED FROM http://stackoverflow.com/a/15036110/592323
//===========================================================================
// META-FUNCTIONS FOR CREATING INDEX LISTS
// The structure that encapsulates index lists
template <size_t... Is>
struct index_list
{
};
// Collects internal details for generating index ranges [MIN, MAX)
namespace detail
{
// Declare primary template for index range builder
template <size_t MIN, size_t N, size_t... Is>
struct range_builder;
// Base step
template <size_t MIN, size_t... Is>
struct range_builder<MIN, MIN, Is...>
{
typedef index_list<Is...> type;
};
// Induction step
template <size_t MIN, size_t N, size_t... Is>
struct range_builder : public range_builder<MIN, N - 1, N - 1, Is...>
{
};
}
// Meta-function that returns a [MIN, MAX) index range
template<size_t MIN, size_t MAX>
using index_range = typename detail::range_builder<MIN, MAX>::type;
//===========================================================================
template<std::size_t I = 0, typename ...Ts>
inline typename std::enable_if<I == sizeof...(Ts), void>::type
tupleIncrement(std::tuple<Ts...> &tup)
{ }
template<std::size_t I = 0, typename ...Ts>
inline typename std::enable_if<I < sizeof...(Ts), void>::type
tupleIncrement(std::tuple<Ts...> &tup)
{
++std::get<I>(tup);
tupleIncrement<I + 1, Ts...>(tup);
}
template<typename ...Ts> // Element types
class WrapMultiVector
{
// references to vectors in a TUPLE
std::tuple<std::vector<Ts>&...> m_vectors;
// list of indices
typedef decltype(index_range<0, sizeof...(Ts)>()) IndexList;
public:
// references to vectors in multiple arguments
WrapMultiVector(std::vector<Ts> & ...vectors)
: m_vectors(vectors...) // construct tuple from multiple args.
{}
class iterator {
std::tuple<typename std::vector<Ts>::iterator...> m_elemIterators;
public:
iterator(std::tuple<typename std::vector<Ts>::iterator...> elemIterators)
: m_elemIterators(elemIterators)
{}
bool operator==(const iterator &o) const {
return std::get<0>(m_elemIterators) == std::get<0>(o.m_elemIterators);
}
bool operator!=(const iterator &o) const {
return std::get<0>(m_elemIterators) != std::get<0>(o.m_elemIterators);
}
iterator& operator ++() {
tupleIncrement(m_elemIterators);
return *this;
}
iterator operator ++(int) {
iterator old = *this;
tupleIncrement(m_elemIterators);
return old;
}
std::tuple<Ts&...> operator*() {
return getElements(IndexList());
}
private:
template<size_t ...Is>
std::tuple<Ts&...> getElements(index_list<Is...>) {
return std::tie(*std::get<Is>(m_elemIterators)...);
}
};
iterator begin() {
return iterator(getBegins(IndexList()));
}
iterator end() {
return iterator(getEnds(IndexList()));
}
private:
template<size_t ...Is>
std::tuple<typename std::vector<Ts>::iterator...> getBegins(index_list<Is...>) {
return std::make_tuple(std::get<Is>(m_vectors).begin()...);
}
template<size_t ...Is>
std::tuple<typename std::vector<Ts>::iterator...> getEnds(index_list<Is...>) {
return std::make_tuple(std::get<Is>(m_vectors).end()...);
}
};
template<typename ...Ts>
WrapMultiVector<Ts...> makeWrapper(std::vector<Ts> & ...vectors) {
return WrapMultiVector<Ts...>(vectors...);
}
int main() {
std::vector<int> id = { 1, 2, 3 };
std::vector<std::string> name = { "Alice", "Bob", "Carol" };
std::vector<int> age = { 30, 42, 55 };
auto nameAge = makeWrapper(name, age);
for (auto na : nameAge) {
std::cout << "name: " << std::get<0>(na) << ", age: " << std::get<1>(na) << std::endl;
}
}