#include <vector>
#include <tuple>
#include <algorithm>
#include <type_traits>

template<class T>
using Invoke = typename T::type;

template<class T>
using Unqualified = Invoke<std::remove_cv<Invoke<std::remove_reference<T>>>>;

template<class T>
using ValueType = typename Unqualified<T>::value_type;

template<class T>
T const& forward_index(std::vector<T> const& v, unsigned i){
    return v[i];
}

template<class T>
T&& forward_index(std::vector<T>&& v, unsigned i){
    return std::move(v[i]);
}

template<class... Vs>
std::vector<std::tuple<ValueType<Vs>...>> zip(Vs&&... vs){
    auto lo = std::min({vs.size()...});
    std::vector<std::tuple<ValueType<Vs>...>> v;
    v.reserve(lo);
    for(unsigned i = 0; i < lo; ++i)
        v.emplace_back(forward_index(std::forward<Vs>(vs), i)...);
    return v;
}

#include <iostream>

int main(){
    std::vector<int> a{1,3,5}, b{2,4,6}, c{3,5,7};
    for(auto&& t : zip(a, b, c)){
        std::cout << std::get<0>(t) << ":" << std::get<1>(t) << ":" << std::get<2>(t) << "\n";
    }
}