为元组实现创建索引序列

时间:2019-03-22 17:11:54

标签: c++ tuples

假设我想自己实现std::tuple之类的东西,仅仅是基础知识。我想先显示失败的尝试。

#include <utility>
#include <iostream>

template <std::size_t I>
struct tuple_index_leaf {
    using Index = std::integral_constant<std::size_t, I>;
    std::size_t i = Index::value;
};

template <std::size_t... Is>
struct tuple_index : tuple_index_leaf<Is>...
{};

template <std::size_t I, std::size_t... Is>
constexpr auto get_index(tuple_index<Is...> const &i) {
    return static_cast<const tuple_index_leaf<I>*>(&i)->i;
}

template <std::size_t I, typename T>
struct tuple_leaf : tuple_index_leaf<I> {
    T elem;
};

template<typename... Ts>
struct tuple : tuple_leaf<sizeof...(Ts), Ts>... {

};

template <std::size_t I, typename... Ts>
auto& get(tuple<Ts...> &t) {
    return static_cast<tuple_leaf<I, float>*>(&t)->elem;
}

int main() {
    tuple_index<0, 1, 2> ti;
    std::cout << get_index<0>(ti) << "\n";
    tuple<int, float> t;
    get<2>(t) = 3.14;
} 

现在,看看get函数。我对最后一个类型float进行了硬编码,并且只能使用索引2来调用它,例如get<2>。这是因为我的tuple构造函数中的缺陷。如果您在那里查看,您会看到我正在将sizeof...(Ts)传递给tuple_leaf。例如,在这种情况下,我所有的元组叶都将像tuple_leaf<2, int>, tuple_leaf<2, float>。我想要的是像tuple_leaf<0, int>, tuple_leaf<1, float>...这样的扩展。我知道,我使用的扩展tuple_leaf<sizeof...(Ts), Ts>...并没有给我这些。我需要某种我想出的索引序列,并开始实现类似tuple_index的东西。但这需要我通过std::size_t...,而我却不知道该怎么做。所以问题是,如何获得像tuple_leaf<0, int>, tuple_leaf<1, float>...这样的扩展?

1 个答案:

答案 0 :(得分:2)

这并不难。这是一个如何执行此操作的示例(不是唯一的方法,这是我很快完成的操作):

#include <utility>
#include <cstddef>

template <std::size_t I, typename T>
struct tuple_leaf {
    T elem;
};

template<class SEQ, class... TYPE> struct tuple_impl;

template<size_t... Ix, class... TYPE>
struct tuple_impl<std::index_sequence<Ix...>, TYPE...> : tuple_leaf<Ix, TYPE>... { };

template<typename... Ts>
struct tuple : tuple_impl<std::make_index_sequence<sizeof...(Ts)>, Ts...> { };


// below lines are for testing
tuple<int, double, char*> tup;

// the fact that this compiles tells us char* has index 2
auto& z = static_cast<tuple_leaf<2, char*>&>(tup);