创建C ++ std :: tuple投影函数

时间:2014-05-12 15:08:36

标签: c++ templates variadic-templates stdtuple

我正在寻找std::tuple的投影功能。即,函数接收整数列表作为模板参数,并返回仅具有这些索引值的元组。

例如,假设我有一个元组tuple<int,String,char,float> t,那么调用project<1,3>(t)会产生tuple<String,float>类型的元组。

当然,关键似乎是递归模板。但是,我无法让它工作。我尝试通过声明一个结构来计算投影操作的返回类型。即使这样也失败了这是我试过的:

template<typename T, size_t... indexes>
class Projection{
};

// Specialization for no index => Empty tuple
template<>
template<typename... T>
class Projection<std::tuple<T...>>{
   typedef std::tuple<T...> InputTuple;
   typedef std::tuple<> Tuple;
};

// Specialization for one or more parameters
template<size_t Index1, size_t... others>
template<typename... T>
class Projection<std::tuple<T...>,Index1,others...>{
    typedef std::tuple<T...> InputTuple;

    // The type of a projection with one column less
    typedef Projection<std::tuple<T...>,others...> TupleMinusOne;

    // The result type is the catenation of TupleMinusOne plus the column projected in this     step
    typedef decltype(std::tuple_cat(std::make_tuple(std::get<Index1>(InputTuple())),typename TupleMinusOne::Tuple())) Tuple;
};

这个编译。带有空元组的基本情况也有效,即:

Projection<std::tuple<int,std::string>>::Tuple t;

导致t为空元组。但是,递归情况不会编译:

Projection<std::tuple<int,std::string>,1>::Tuple t;

我收到以下错误:

Test.cpp:79:1: error: ‘Tuple’ is not a member of ‘Projection<std::tuple<int, float>, 1ul>’

所以似乎无法识别递归情况,但为什么呢?

2 个答案:

答案 0 :(得分:4)

很少需要递归模板; pack expansion通常更清晰,更简单。在这种情况下,只需使用tuple_element

template<typename T, size_t... indexes>
class Projection{
public:
    using Tuple = std::tuple<typename std::tuple_element<indexes, T>::type...>;
};

同样为project

template<size_t... indexes, typename T>
auto project(const T &t) -> typename Projection<T, indexes...>::Tuple {
    return typename Projection<T, indexes...>::Tuple(std::get<indexes>(t)...);
}

答案 1 :(得分:1)

您可以使用以下内容:

#define Return(ret) decltype(ret) { return ret; }

template<std::size_t... Is, typename T>
auto project(const T& t) -> Return(std::make_tuple(std::get<Is>(t)...))