如何反转整数参数包

How to reverse an integer parameter pack?

本文关键字:参数 整数 何反转      更新时间:2023-10-16

遗憾的是,我不能使用C++中的任何stl/std库,因为我是为嵌入式操作系统编程的,该操作系统只有可用的带有裸C++的gcc4.4.4,因此没有std::tuplestd::forwardstd::applystd::anything_else

为了帮助理解元通用生成代码,我将展示一个用clang编译的最小示例代码,因为它可以向我们展示生成的模板元编程/元编程代码。

这个问题只是为了好奇,因为我可以按照正确的顺序创建它,而不是按照错误的顺序生成整数参数包。这是我用来在错误的顺序上生成整数包装包的东西:

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...}进行演示。实际使用的代码是这样的:

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' ):这样的输入,它生成以下内容

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看到生成的代码:

$ 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}

我设法按照正确的顺序生成了列表,只是在示例代码中更改了这一行:

< AccumulatedSize + sizeof(Head), Grouper( Tail... ), GeneratedSequence..., AccumulatedSize
// to -->
< AccumulatedSize + sizeof(Head), Grouper( Tail... ), AccumulatedSize, GeneratedSequence...

但我们假设我不能这样做,因为列表是从第三部分输入的,我无法控制。如何在不使用任何std库函数的情况下将参数包<5, 1, 0>反转为<0, 1, 5>

在我的第一次尝试中,我尝试使用与生成整数列表相同的策略,但我无法编译:

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;
}

当我试图构建这个时,我得到了这个错误:

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>
^

参考文献:

参数列表中的变分模板、参数包及其讨论的模糊性
  • "拆包";调用匹配函数指针的元组
  • 我们能看到C++编译器实例化的模板代码吗
  • 使用可变模板构建函数参数
  • 如何反转可变模板函数的参数顺序
  • 如何在不使用任何std库函数的情况下将参数pack <5, 1, 0>反转为<0, 1, 5>

    不知道你到底能用什么,但。。。这对我来说似乎很容易。

    给定如下所示的辅助结构

    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; };
    

    revert结构可以是简单的

    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打印序列,但显然可以将其删除(。

    #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()));
    }