将一个参数包转换为另一个参数包?

时间:2015-08-04 13:04:02

标签: c++11 metaprogramming c++14

我想将迭代器类型的参数包转换为相应的引用参数包。这是我到目前为止所得到的:

template <class Iterator, class... Iterators>
class cast_iterators_to_references
{
    using head_reference_type = std::iterator_traits<Iterator>::reference

    // TODO
    //using type = ;
};

我从哪里拿到它?

我这样做的原因是创建一个“视图”对象。它包含一个它所引用的容器的迭代器元组。我想有一个方法在某个索引处返回一个元素元组,这样我就可以为它创建一个自定义迭代器,创建开始和结束方法,并在基于范围的for语句中使用它。

以下是它的使用方法:

template<class Iterators...>
tuple_iterator
{
public:
    using tuple_type = std::tuple<Iterators...>;
    using references = cast_iterators_to_references<Iterators...>;
    using tuple_element_type = std::tuple<references>;

    // ... construct from tuple, copy/move constructors, copy/move assignment etc.

    tuple_element_type operator[](size_t index)
    {
        tuple_element_type element;
        for (size_t i = 0; i < sizeof...(Iterators); i++)
            std::get<i>(element) = std::get<i>(data_)[offset_ + index];

        return element;
    }

    // ... increment, decrement operators etc.

private:
    tuple_type data_;
    size_t offset_;
}

1 个答案:

答案 0 :(得分:0)

参数包不是一流的,因此处理它们有点繁琐。

cast_iterators_to_references元函数的第一次尝试可能是这样的:

// Not defined, used to wrap a pack into a type
template <class...> struct pack;

template <class... Iterators>
using cast_iterators_to_references = pack<
    typename std::iterator_traits<Iterators>::reference...
>;

但是你需要帮助类来通过模式匹配解压缩pack

template <class> unpack_to_tuple;

template <class... Ts> unpack_to_tuple<pack<Ts...>> {
    using type = std::tuple<Ts...>;
};

// In your class
using references = cast_iterators_to_references<Iterators...>;
using tuple_element_type = typename unpack_to_tuple<references>::type;

所以你最好直接使用参数包:

using tuple_element_type = std::tuple<
    typename std::iterator_traits<Iterators>::reference...
>;

您的operator[]可以写成如下:

template <std::size_t... Idx>
auto access(size_t index, std::index_sequence<Idx...>) {
    return std::tie(std::get<Idx>(data_)[index + offset_]...);
}

tuple_element_type operator[](size_t index)
{
    return access(index, std::index_sequence_for<Iterators...>{});
}