假设:
make_pack_indices<START, END>::type
是pack_indices<START, START+1, START+2, ..., END-1>
make_reverse_indices<std::size_t SIZE>::type
是pack_indices<SIZE-1, SIZE-2, ..., 2, 1, 0>
make_rotated_indices<SIZE, SHIFT>::type
是pack_indices<SHIFT, SHIFT+1, ..., SIZE-1, 0, 1, 2, ..., SHIFT-1>
make_alternating_indices<SIZE, START, INTERVAL>::type
是pack_indices<START, START + INTERVAL, START + 2 * INTERVAL, ...>
类型,直到达到小于START
的最大索引。
如何通过某种组合(如
)执行这些形式的make_indices的组合compose<A, C, B, A..., D>::type,
其中A,B,C,D
是代表上述四种make_indices
类型的类型(仿函数或其他)?例如,
A = make_pack_indices<1,4>
B = make_reverse_indices<5>
C = make_rotated_indices<5,2>
然后
compose<B,C,A>::type
将是
pack_indices<4,3,2,1,0> -> pack_indices<2,1,0,4,3> -> pack_indices<1,0,4>
一个更简单的例子是
compose <make_rotated_indices<10,2>, make_rotated_indices<10,4>>::type
将是
make_rotated_indices<10,6>::type.
这是一个应用程序。假设我们有参数包
('a', 3.14 , 5, "home", '!', 4.5, "car", 20, 0.5, 'b')
我们可以使用我的make_reverse_indices&lt; 10&gt;来反转它,并且我们可以使用make_rotated_indices&lt; 10,3&gt;将它旋转到左边3。但是假设我想要反转包然后向左旋转3.而不是手动执行一个跟随另一个,我想要定义一个将使用make_reverse_indices&lt; 10&gt;的组合结构。和make_rotated_indices&lt; 10,3&gt;作为参数并一次性给出所需的结果,这将是
("car", 4.5, '!', "home", 5, 3.14, 'a', 'b', 0.5, 20)
我认为(在上面的例子中)make_reverse_indices&lt; 10&gt;和make_rotated_indices&lt; 10,3&gt;他们自己需要转换成别的东西。 make_reverse_indices&LT; 10 -10给出9,8,7,...,1,0。所以make_rotated_indices&lt; 10,3&gt; (而不是给3,4,5,... 9,0,1,2)需要转换成另一个接受参数包9,8,7,...,1,0然后执行的函数make_rotated_indices&lt; 10,3&gt;的效果,从而给出6,5,4,... 0,9,8,7。我正在研究的另一个想法是:定义一个辅助函数来从rotate_indices&lt; 10,3&gt; :: type中提取索引,将其转换为参数包,然后应用make_rotated_indices&lt; 10,3&gt;在那个参数包上。
这是我已经拥有的代码,以防任何人需要它进行测试(结构本身已经彻底测试过):
#include <iostream>
#include <string>
#include <tuple>
template<std::size_t...>
struct pack_indices
{
using type = pack_indices;
};
constexpr int positiveModulo(int i, int n)
{
return (i % n + n) % n;
}
template<std::size_t START, std::size_t END, std::size_t... INDICES>
struct make_indices : make_indices<START + 1, END, INDICES..., START>
{};
template<std::size_t END, std::size_t... INDICES>
struct make_indices<END, END, INDICES...> : pack_indices <INDICES...>
{};
template<std::size_t SIZE, std::size_t... INDICES>
struct make_reverse_indices : make_reverse_indices<SIZE - 1, INDICES..., SIZE - 1>
{};
template<std::size_t... INDICES>
struct make_reverse_indices<0, INDICES...> : pack_indices<INDICES...>
{};
template<std::size_t SIZE, std::size_t SHIFT, std::size_t SHIFT_, std::size_t... INDICES>
struct make_rotated_indices_helper
: make_rotated_indices_helper<SIZE, SHIFT, SHIFT_ + 1, INDICES..., positiveModulo(SHIFT + SHIFT_, SIZE)>
{};
template<std::size_t SIZE, std::size_t SHIFT, std::size_t...INDICES>
struct make_rotated_indices_helper<SIZE, SHIFT, SIZE, INDICES...> : pack_indices<INDICES...>
{};
template<std::size_t SIZE, std::size_t SHIFT, std::size_t... INDICES>
struct make_rotated_indices
{
using type = make_rotated_indices_helper<SIZE, SHIFT, 0, INDICES...>;
};
template<std::size_t SIZE, std::size_t START, std::size_t INTERVAL, std::size_t NUM_LEFT, std::size_t... INDICES>
struct make_alternating_indices_helper
: make_alternating_indices_helper<SIZE, START + INTERVAL, INTERVAL, NUM_LEFT - 1, INDICES..., positiveModulo(START, SIZE)>
{};
template<std::size_t SIZE, std::size_t START, std::size_t INTERVAL, std::size_t... INDICES>
struct make_alternating_indices_helper<SIZE, START, INTERVAL, 0, INDICES...>
: pack_indices<INDICES...>
{};
template<std::size_t SIZE, std::size_t START, std::size_t INTERVAL, std::size_t... INDICES>
struct make_alternating_indices
{
using type = make_alternating_indices_helper<SIZE, START, INTERVAL, (SIZE - 1) / INTERVAL + 1>;
};
// Testing
namespace Pack
{
template<typename LAST>
void print(LAST && last)
{
std::cout << std::forward<LAST>(last) << std::endl;
}
template<typename FIRST, typename... REST>
void print(FIRST && first, REST&&... rest)
{
std::cout << std::forward<FIRST>(first) << ", ";
print<REST...>(std::forward<REST>(rest)...);
}
}
template<typename TUPLE, std::size_t... INDICES>
void showValuesHelper(TUPLE&& tuple,
const pack_indices<INDICES...>&)
{
Pack::print(std::get<INDICES>(std::forward<TUPLE>(tuple))...);
}
template<std::size_t START, std::size_t END, typename... TYPES>
void showMiddleValues(TYPES && ...types)
{
const auto tuple = std::forward_as_tuple(std::forward<TYPES>(types)...);
const typename make_indices<START, END>::type indices;
showValuesHelper (tuple, indices);
}
int main()
{
std::cout << "original argument pack: ";
Pack::print('a', 3.14, 5, "home", '!', 4.5, "car", 20, 0.5, 'b');
std::cout << "showMiddleValues<2,7> = ";
showMiddleValues<2, 7>('a', 3.14, 5, "home", '!', 4.5, "car", 20, 0.5, 'b'); // 5, home, !, 4.5, car
}
答案 0 :(得分:0)
一种可能的解决方案可能是使用简单递归和二进制连接:
template<typename LHS , typename RHS>
struct concat;
template<std::size_t... Is , std::size_t... Js>
struct concat<sequence<Is...>,sequence<Js...>>
{
using type = sequence<Is...,Js...>;
};
template<typename... Ss>
struct multi_concat;
template<typename HEAD , typename... TAIL>
struct multi_concat<HEAD,TAIL...>
{
using type = typename concat<HEAD,typename multi_concat<TAIL...>::type>::type;
};
template<>
struct multi_concat<>
{
using type = sequence<>;
};
答案 1 :(得分:0)
这只是我想要实现的目标的开始。它不是一般化的,因为它仅仅是为了旋转而进行的(它是自组合而不是任意多种函数的一般组成):
template <int N, std::size_t SHIFT, std::size_t... INDICES>
struct rotateAgain;
template <int N, std::size_t SHIFT, typename... TYPES> // N is the number of times rotation by SHIFT is being done
void rotatePack (TYPES&&... types) {
const typename make_rotated_indices<sizeof...(TYPES), SHIFT>::type indices;
rotateAgain<N-1, SHIFT>()(indices, types...);
}
template <int N, std::size_t SHIFT, std::size_t... INDICES>
struct rotateAgain {
template <typename... TYPES>
void operator() (const pack_indices<INDICES...>&, const TYPES&... types) const {
const typename make_rotated_indices<sizeof...(TYPES), SHIFT>::type indices;
Pack::print (Pack::get<INDICES>(types...)...);
rotatePack<N, SHIFT> (Pack::get<INDICES>(types...)...);
}
};
template <std::size_t SHIFT, std::size_t... INDICES>
struct rotateAgain<0, SHIFT, INDICES...> {
template <typename... TYPES>
void operator() (const pack_indices<INDICES...>&, const TYPES&... types) const {
std::cout << "End of recursion" << std::endl;
}
};
必须有一些方法可以将make_rotated_indices(上面使用的)一般化到定义的任何make_indices类型。