如何反转整数参数包? [英] How to reverse an integer parameter pack?
问题描述
可悲的是,我不能使用 stl 的任何问题 / std 库的问题,因为我正在为嵌入式操作系统,仅具有可用的 gcc std::tuple
,std::forward
,std::apply
或std::anything_else
.
Sadly, I cannot use any of stl/std libraries from C++, because I am programming for a embedded Operating System which only has available gcc 4.4.4
with bare C++, so, no std::tuple
, std::forward
, std::apply
or std::anything_else
.
为帮助您理解生成的元通用代码,我将展示一个使用 clang ,因为它可以选择向我们显示生成的 template-meta-programming /
To help understand meta generic generated code, I am presenting a minimal example code compiled with clang because it has a option to show us the generated template-meta-programming/metaprogramming code.
这个问题只是出于好奇,因为我可以以正确的顺序创建它,而不是以错误的顺序生成整数参数包.这是我用来按错误顺序生成整数打包程序包的方法:
This question is just for curiosity because instead of generating the integer parameter pack in the wrong order, I can just create it on a correct order. This is what I use to generate my integer packager pack on the wrong order:
template<int ...>
struct MetaSequenceOfIntegers { };
template<int AccumulatedSize, typename Tn, int... GeneratedSequence>
struct GeneratorOfIntegerSequence;
template<int AccumulatedSize, typename Grouper, typename Head, typename... Tail, int... GeneratedSequence>
struct GeneratorOfIntegerSequence< AccumulatedSize, Grouper( Head, Tail... ), GeneratedSequence... >
{
typedef typename GeneratorOfIntegerSequence
< AccumulatedSize + sizeof(Head), Grouper( Tail... ), AccumulatedSize, GeneratedSequence...
>::type type;
};
template<int AccumulatedSize, typename Grouper, int... GeneratedSequence>
struct GeneratorOfIntegerSequence<AccumulatedSize, Grouper(), GeneratedSequence...>
{
typedef MetaSequenceOfIntegers<GeneratedSequence...> type;
};
template<int ...Sequence>
void intergers_sequencer_generator(MetaSequenceOfIntegers<Sequence...>) {
int array[] = {Sequence...};
}
int main(int argc, char const *argv[]) {
intergers_sequencer_generator( GeneratorOfIntegerSequence< 0, int(char, int, char) >::type() );
return 0;
}
我仅使用int array[] = {Sequence...}
进行演示.实际使用的代码是这样的:
I am only using int array[] = {Sequence...}
for demonstration. The real code used is like this:
template<typename ReturnType, typename... Tn>
class Closure
{
// ... other code
template<int ...Sequence>
ReturnType _run(MetaSequenceOfIntegers<Sequence...>) {
return _function_entry_pointer( get_nth_function_argument_on_address<Sequence, Tn>()... );
}
// ... other code
}
为以下输入生成此波纹管,例如create_functor( &function1, 'a', 10, 'b' )
:
Which generates this bellow, for an input like create_functor( &function1, 'a', 10, 'b' )
:
template <int ...Sequence> char _run(MetaSequenceOfIntegers<Sequence...>);
template<> char _run<<5, 1, 0>>(MetaSequenceOfIntegers<5, 1, 0>) {
return this->_function_entry_pointer(
this->get_nth_function_argument_on_address<5, const char *>(),
this->get_nth_function_argument_on_address<1, const char *>(),
this->get_nth_function_argument_on_address<0, char>()
);
}
// and much more
我们可以使用clang 查看生成的代码:
We can see the generated code using clang:
$ clang++ -Xclang -ast-print -fsyntax-only generator.cpp > expanded.cpp
template <int ...> struct MetaSequenceOfIntegers {
};
template<> struct MetaSequenceOfIntegers<<5, 1, 0>> {
};
template <int AccumulatedSize, typename Tn, int ...GeneratedSequence> struct GeneratorOfIntegerSequence
template<> struct GeneratorOfIntegerSequence<0, int (char, int, char), <>> {
typedef typename GeneratorOfIntegerSequence<0 + sizeof(char), int (int, char), 0>::type type;
}
template<> struct GeneratorOfIntegerSequence<1, int (int, char), <0>> {
typedef typename GeneratorOfIntegerSequence<1 + sizeof(int), int (char), 1, 0>::type type;
}
template<> struct GeneratorOfIntegerSequence<5, int (char), <1, 0>> {
typedef typename GeneratorOfIntegerSequence<5 + sizeof(char), int (), 5, 1, 0>::type type;
}
template<> struct GeneratorOfIntegerSequence<6, int (), <5, 1, 0>> {
typedef MetaSequenceOfIntegers<5, 1, 0> type;
};
template <int AccumulatedSize, typename Grouper, typename Head, typename ...Tail, int ...GeneratedSequence> struct GeneratorOfIntegerSequence<AccumulatedSize, type-parameter-0-1 (type-parameter-0-2, type-parameter-0-3...), <GeneratedSequence...>> {
typedef typename GeneratorOfIntegerSequence<AccumulatedSize + sizeof(Head), Grouper (Tail...), AccumulatedSize, GeneratedSequence...>::type type;
};
template <int AccumulatedSize, typename Grouper, int ...GeneratedSequence> struct GeneratorOfIntegerSequence<AccumulatedSize, type-parameter-0-1 (), <GeneratedSequence...>> {
typedef MetaSequenceOfIntegers<GeneratedSequence...> type;
};
template <int ...Sequence> void intergers_sequencer_generator(MetaSequenceOfIntegers<Sequence...>) {
int array[] = {Sequence...};
}
template<> void intergers_sequencer_generator<<5, 1, 0>>(MetaSequenceOfIntegers<5, 1, 0>) {
int array[] = {5, 1, 0};
}
int main(int argc, const char *argv[]) {
intergers_sequencer_generator(GeneratorOfIntegerSequence<0, int (char, int, char)>::type());
return 0;
}
生成元编程列表的顺序是我需要的相反顺序.代替int array[] = {5, 1, 0}
,它应该是int array[] = {0, 1, 5}
.
The meta programming list is generated is on reversed order I need it to be. Instead of int array[] = {5, 1, 0}
, it should be int array[] = {0, 1, 5}
.
我只是在示例代码中更改了这一行,才设法以正确的顺序生成了列表:
I managed to generated the list on the correct order just changing this line on in example code:
< AccumulatedSize + sizeof(Head), Grouper( Tail... ), GeneratedSequence..., AccumulatedSize
// to -->
< AccumulatedSize + sizeof(Head), Grouper( Tail... ), AccumulatedSize, GeneratedSequence...
但是让我们假设我不能这样做,因为该列表是从我没有控制权的第三部分输入的.如何在不使用任何标准库函数的情况下将参数包<5, 1, 0>
反向转换为<0, 1, 5>
?
But let us supposed I could not do that because the list is input from a third part which I do not have control. How can I reverse the parameter pack <5, 1, 0>
to <0, 1, 5>
without using any std library functions?
在我的第一次尝试中,我尝试使用与生成整数列表相同的策略,但是无法对其进行编译:
In my first attempt, I tried to use the same strategy as the one I did to generate the integer list, but I could not make it to compile:
template<int ...>
struct MetaSequenceOfIntegers { };
template<int AccumulatedSize, typename Tn, int... GeneratedSequence>
struct GeneratorOfIntegerSequence;
template<int AccumulatedSize, typename Grouper, typename Head, typename... Tail, int... GeneratedSequence>
struct GeneratorOfIntegerSequence< AccumulatedSize, Grouper( Head, Tail... ), GeneratedSequence... >
{
typedef typename GeneratorOfIntegerSequence
< AccumulatedSize + sizeof(Head), Grouper( Tail... ), AccumulatedSize, GeneratedSequence...
>::type type;
};
template<int AccumulatedSize, typename Grouper, int... GeneratedSequence>
struct GeneratorOfIntegerSequence<AccumulatedSize, Grouper(), GeneratedSequence...>
{
typedef MetaSequenceOfIntegers<GeneratedSequence...> type;
};
// The new code starts here
template<int ...>
struct MetaSequenceReversed { };
template<typename Tn, int... GeneratedSequence>
struct ReversorOfIntegerSequence;
template<typename Grouper, int Head, int... Tail, int... GeneratedSequence>
struct ReversorOfIntegerSequence< Grouper( Head, Tail... ), GeneratedSequence... >
{
typedef typename ReversorOfIntegerSequence
< Grouper( Tail... ), GeneratedSequence...
>::type type;
};
template<typename Grouper, int... GeneratedSequence>
struct ReversorOfIntegerSequence<Grouper(), GeneratedSequence...>
{
typedef MetaSequenceReversed<GeneratedSequence...> type;
};
template<int ...ReversedSequence>
void intergers_sequencer_reversor(MetaSequenceReversed<ReversedSequence...>) {
int reversed_array[] = {ReversedSequence...};
}
template<int ...Sequence>
void intergers_sequencer_generator(MetaSequenceOfIntegers<Sequence...>) {
int array[] = {Sequence...};
intergers_sequencer_reversor( ReversorOfIntegerSequence< int(Sequence...) >::type() );
}
int main(int argc, char const *argv[])
{
intergers_sequencer_generator( GeneratorOfIntegerSequence< 0, int(char, int, char) >::type() );
return 0;
}
当我尝试构建它时,出现此错误:
When I try to build this, I got this error:
generator.cpp:29:35: error: template argument for template type parameter must be a type
struct ReversorOfIntegerSequence< Grouper( Head, Tail... ), GeneratedSequence... >
^~~~~~~~~~~~~~~~~~~~~~~~
generator.cpp:25:19: note: template parameter is declared here
template<typename Tn, int... GeneratedSequence>
^
generator.cpp:50:62: error: template argument for template type parameter must be a type
intergers_sequencer_reversor( ReversorOfIntegerSequence< int(Sequence...) >::type() );
^~~~~~~~~~~~~~~~
generator.cpp:25:19: note: template parameter is declared here
template<typename Tn, int... GeneratedSequence>
^
参考文献:
References:
- Variadic templates, parameter pack and its discussed ambiguity in a parameter list
- "unpacking" a tuple to call a matching function pointer
- Can we see the template instantiated code by C++ compiler
- Build function parameters with variadic templates
- How to reverse the order of arguments of a variadic template function?
推荐答案
如何在不使用任何标准库函数的情况下将参数
pack <5, 1, 0>
转换为<0, 1, 5>
?
不确定要确切地使用什么功能,但是...对我来说似乎很容易.
Not sure to understand what do you exactly can use but... it seems easy to me.
给出如下的帮助结构
template <typename, typename>
struct RS_helper;
template <int ... As, int B0, int ... Bs>
struct RS_helper<MetaSequenceOfIntegers<As...>,
MetaSequenceOfIntegers<B0, Bs...>>
: RS_helper<MetaSequenceOfIntegers<B0, As...>,
MetaSequenceOfIntegers<Bs...>>
{ };
template <typename T>
struct RS_helper<T, MetaSequenceOfIntegers<>>
{ using type = T; };
还原结构可以很简单
template <int ... Is>
struct RevertSequence
: RS_helper<MetaSequenceOfIntegers<>, MetaSequenceOfIntegers<Is...>>
{ };
我想反向函数可能有用
template <int ... Is>
constexpr typename RevertSequence<Is...>::type
revertSequenceFunction (MetaSequenceOfIntegers<Is...> const &)
{ return {}; }
我建议对原始代码进行修改,并增加反向序列(也使用std::cout
打印序列,但显然可以将其删除).
I propose a modified version of your original code with addition of reversed sequence (using also std::cout
to print the sequences, but you can remove it, obviously).
#include <iostream>
template <int ...>
struct MetaSequenceOfIntegers
{ };
template <int AccumulatedSize, typename Tn, int ... GeneratedSequence>
struct GeneratorOfIntegerSequence;
template <int AccumulatedSize, typename Grouper, typename Head,
typename ... Tail, int ... GeneratedSequence>
struct GeneratorOfIntegerSequence<AccumulatedSize, Grouper(Head, Tail...),
GeneratedSequence... >
{ typedef typename GeneratorOfIntegerSequence
<AccumulatedSize+sizeof(Head), Grouper(Tail...),
AccumulatedSize, GeneratedSequence...>::type type; };
template <int AccumulatedSize, typename Grouper, int ... GeneratedSequence>
struct GeneratorOfIntegerSequence<AccumulatedSize, Grouper(),
GeneratedSequence...>
{ typedef MetaSequenceOfIntegers<GeneratedSequence...> type; };
template <int ... Sequence>
void intergers_sequencer_generator(MetaSequenceOfIntegers<Sequence...>)
{
using unused = int[];
(void)unused { 0, (std::cout << Sequence << ' ', 0)... };
std::cout << std::endl;
}
template <typename, typename>
struct RS_helper;
template <int ... As, int B0, int ... Bs>
struct RS_helper<MetaSequenceOfIntegers<As...>,
MetaSequenceOfIntegers<B0, Bs...>>
: RS_helper<MetaSequenceOfIntegers<B0, As...>,
MetaSequenceOfIntegers<Bs...>>
{ };
template <typename T>
struct RS_helper<T, MetaSequenceOfIntegers<>>
{ using type = T; };
template <int ... Is>
struct RevertSequence
: RS_helper<MetaSequenceOfIntegers<>, MetaSequenceOfIntegers<Is...>>
{ };
template <int ... Is>
constexpr typename RevertSequence<Is...>::type
revertSequenceFunction (MetaSequenceOfIntegers<Is...> const &)
{ return {}; }
int main ()
{
intergers_sequencer_generator(
GeneratorOfIntegerSequence<0, int(char, int, char)>::type());
intergers_sequencer_generator(
revertSequenceFunction(
GeneratorOfIntegerSequence<0, int(char, int, char)>::type()));
}
这篇关于如何反转整数参数包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!