C++ 11可变参数模板:从变量矢量列表返回元组

dul*_*uli 14 c++ templates variadic-templates c++11

我想写一些类似于python zip的东西(http://docs.python.org/2/library/functions.html).zip应该接收不同类型的可变数量的向量,并返回元组的向量,截断为最短输入的长度.

例如

x = [1, 2, 3]
v = ['a', 'b']
Run Code Online (Sandbox Code Playgroud)

我希望输出是一个向量 [ <1, 'a'>, <2, 'b'>]

我如何在C++ 11中执行此操作?

Xeo*_*Xeo 19

热切地这样做,只有复制才很容易:

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

template<class... Ts>
std::vector<std::tuple<Ts...>> zip(std::vector<Ts> const&... vs){
    auto lo = std::min({vs.size()...});
    std::vector<std::tuple<Ts...>> v;
    v.reserve(lo);
    for(unsigned i = 0; i < lo; ++i)
        v.emplace_back(vs[i]...);
    return v;
}
Run Code Online (Sandbox Code Playgroud)

实例.

通过完美的转发和允许移出向量,它变得有点复杂,主要是由于帮助者:

#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;
}
Run Code Online (Sandbox Code Playgroud)

实例.

  • 我想知道移动语义的用法.看起来第二个模板函数`forward_index`从未使用过,因为`vs`是一个左值引用.我认为它应该改为`forward_index(std :: forward <Vs>(vs),i)...`? (2认同)

nos*_*sid 5

以下模板功能可能是一个很好的起点.

template <typename ...Types>
auto zip(const std::vector<Types>&... values)
    -> std::vector<std::tuple<Types...>>
{
    auto size = std::min({ values.size()... });
    std::vector<std::tuple<Types...>> result;
    for (std::size_t i = 0; i != size; ++i) {
        result.emplace_back(values[i]...);
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)