模板递归与许多基本情况

时间:2014-06-14 21:20:01

标签: c++ templates recursion case base

目标是通过将其组件放在START位置然后跳过每个INTERVAL组件,从另一个元组创建一个元组(并提取其类型)。甚至不需要参数包:

template <int NUM_LEFT, int START, int INTERVAL>
struct alternating_tuple_helper {
    template <typename TUPLE>
    auto operator() (const TUPLE& t) const
    -> decltype (std::tuple_cat (std::make_tuple (std::get<START>(t)), alternating_tuple_helper<NUM_LEFT - INTERVAL, START + INTERVAL, INTERVAL>()(t))) {
        return std::tuple_cat (std::make_tuple (std::get<START>(t)), alternating_tuple_helper<NUM_LEFT - INTERVAL, START + INTERVAL, INTERVAL>()(t));
    }
};

template <int START, int INTERVAL>
struct alternating_tuple_helper<0, START, INTERVAL> { // first base case   
    template <typename TUPLE>
    std::tuple<> operator() (const TUPLE& t) const {return std::tuple<>();}
};

template <int START, int INTERVAL>
struct alternating_tuple_helper<-1, START, INTERVAL> { // second base case
    template <typename TUPLE>
    std::tuple<> operator() (const TUPLE& t) const {return std::tuple<>();}
};

// ...基本案例必须涵盖0,-1,-2,......下至-INTERVAL + 1。怎么做?

template <typename TUPLE, int START = 0, int INTERVAL = 2>  // extracting the type
struct alternating_tuple_type {
    using type = decltype (alternating_tuple_helper<std::tuple_size<TUPLE>::value - START, START, INTERVAL>()(std::declval<TUPLE>()));
};

template <typename TUPLE, int START = 0, int INTERVAL = 2>  // getting the new tuple itself
typename alternating_tuple_type<TUPLE, START, INTERVAL>::type alternating_tuple (const TUPLE& t) {
    return alternating_tuple_helper<std::tuple_size<TUPLE>::value - START, START, INTERVAL>()(t);
}

如何使用任意值INTERVAL处理所有基本案例?代码工作正常,并测试INTERVAL大小最多10(是的,目前我使用宏来覆盖0,-1,-2,...,-10,但当然是臭)。

我试过

template <int NUM_LEFT, int START, int INTERVAL>
struct alternating_tuple_helper {
    template <typename TUPLE>
        auto operator() (const TUPLE& t) const 
        -> std::conditional<(NUM_LEFT > 0), decltype (std::tuple_cat (std::make_tuple (std::get<START>(t)), alternating_tuple_helper<NUM_LEFT - INTERVAL, START + INTERVAL, INTERVAL>()(t))), std::tuple<>> {
            return (NUM_LEFT > 0) ? std::tuple_cat (std::make_tuple (std::get<START>(t)), alternating_tuple_helper<NUM_LEFT - INTERVAL, START + INTERVAL, INTERVAL>()(t))
                : std::tuple<>();
    }
};

但它不会编译,因为它以某种方式与alternating_tuple_type冲突(这是为了提取类型)。也许只有那部分需要修复。但我不确定究竟是什么问题。

1 个答案:

答案 0 :(得分:1)

您可以使用此技术创建逻辑测试:

#include <utility>

template<int n, int m, class=void>
struct count{
  enum{value=1 +count<n-m, m>::value};
};
template<int n, int m>
struct count<n,m, typename std::enable_if<(n<m)>::type>{
  enum{value=0};
};

live example

要漂亮模板签名,您可以将void hack粘贴到实现详细信息命名空间中,并将公共接口转发到那里。