繁体   English   中英

我如何递归元组?

[英]How do I recurse tuples?

我正在尝试创建一个可变参数模板容器,用于存储元素向量元组。 这个容器的要点是所有向量上的元素都是相关的,我想稍后保持这种相关性,但它不是计算所必需的。 想象一下,如果你愿意,可以使用vector_3和某种类型的ref_id。

容器只会将载体一致地变异。 所以我理解的部分看起来像这样:

template<typename ...Elems>
class container
{
    std::tuple<std::vector<Elems>...> data_;

public:
    template<typename I>
    const typename std::tuple_element<I, data_type>::type &nth_index() const
    { return std::get<I>(data_); }
};

我正在努力使用插入方法。 我正在思考以下问题:

void push_back(std::tuple<Elems...> &values)
{
    std::tuple<std::back_insert_iterator<std::vector<Elems>>...> inserters;
}

但我不知道如何初始化这个“插入器”元组。 我一直在关注stackoverflow上的各种递归模板示例,我无法将它全部保留在我脑海中足够长的时间来理解它。

我假设我有这样一个元组,我可以使用简单的赋值:

inserters = values;

我还想在所有返回值元组的数组中编写一个访问器:

std::tuple<Elems &...> operator[](const size_t index)
{
     ...
}

但是再一次,我不知道如何初始化这个元组。

我不可能是唯一一个想要这样做的人,我找不到一个很好的资源来学习它。 与此同时,我正在尝试消化0x的原始可变参数模板提议。 洞察力将不胜感激。 我受到MSVC 2012实施的限制。

#include <vector>
#include <tuple>
#include <cstddef>
#include <utility>

template <typename... Elems>
class container
{
    using data_type = std::tuple<std::vector<Elems>...>;

    data_type data_;

public:    
    template <std::size_t I>
    const typename std::tuple_element<I, data_type>::type& nth_index() const
    { return std::get<I>(data_); }

    void push_back(const std::tuple<Elems...>& values)
    {
        return push_back(std::make_index_sequence<sizeof...(Elems)>{}, values);
    }    

    std::tuple<Elems&...> operator[](std::size_t index)
    {
        return get_elems(std::make_index_sequence<sizeof...(Elems)>{}, index);
    }

private:
    template <std::size_t... Is>
    void push_back(std::index_sequence<Is...>, const std::tuple<Elems...>& values)
    {
        using expand = int[];
        static_cast<void>(expand{ 0, (std::get<Is>(data_).push_back(std::get<Is>(values)), 0)... });
    }

    template <std::size_t... Is>
    std::tuple<Elems&...> get_elems(std::index_sequence<Is...>, std::size_t index)
    {
        return std::forward_as_tuple(std::get<Is>(data_)[index]...);
    }
};

DEMO

具有SFINAE和类型特征的C ++ 11解决方案:

template<typename ...Elems>
class container {
  std::tuple<std::vector<Elems>...> data_;

  template<std::size_t N>
  typename std::enable_if<(N <std::tuple_size<decltype(data_)>::value), int>::type
  push_back_impl(std::tuple<Elems...> const &values) {
    std::get<N>(data_).push_back(std::get<N>(values));
    return push_back_impl<N + 1>(values);
  }

  template<std::size_t N>
  typename std::enable_if<(N == std::tuple_size<decltype(data_)>::value), int>::type
  push_back_impl(std::tuple<Elems...> const &values) {
    return 0;
  }

public:

  void push_back(std::tuple<Elems...> const &values) {
     push_back_impl<0>(values);
  }

};

现场演示

至于下标运算符,你需要在这个SO答案中找到一些额外的机器:

template <size_t ...I>
struct index_sequence {};

template <size_t N, size_t ...I>
struct make_index_sequence : public make_index_sequence<N - 1, N - 1, I...> {};

template <size_t ...I>
struct make_index_sequence<0, I...> : public index_sequence<I...> {};

template<typename ...Elems>
class container {
  std::tuple<std::vector<Elems>...> data_;

  template<size_t ...I>
  std::tuple<Elems&...> access_impl(std::size_t const idx, index_sequence<I...>) {
    return std::tie(std::get<I>(data_)[idx]...);
  }

public:

  std::tuple<Elems&...> operator[](std::size_t const idx) {
    return access_impl(idx, make_index_sequence<sizeof...(Elems)>());
  }
};

现场演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM