代码之家  ›  专栏  ›  技术社区  ›  Evandro Coan

如何反转整数参数包?

  •  -1
  • Evandro Coan  · 技术社区  · 7 年前

    / 来自C++的库,因为我正在为一个只有可用的嵌入式操作系统编程。 4.4.4 用裸露的C++,所以,没有 std::tuple , std::forward , std::apply std::anything_else

    为了帮助理解元泛型生成的代码,我提供了一个用 因为它可以显示生成的 代码。

    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++ -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...
    

    但是让我们假设我不能这样做,因为列表是从第三部分输入的,我没有控制权。如何反转参数包 <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>
                      ^
    

    参考文献:

    1. Variadic templates, parameter pack and its discussed ambiguity in a parameter list
    2. "unpacking" a tuple to call a matching function pointer
    3. Can we see the template instantiated code by C++ compiler
    4. Build function parameters with variadic templates
    5. How to reverse the order of arguments of a variadic template function?
    1 回复  |  直到 7 年前
        1
  •  4
  •   max66    7 年前

    如何反转参数 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()));
     }