【问题标题】:How to reverse an integer parameter pack?如何反转整数参数包?
【发布时间】:2018-11-04 20:33:54
【问题描述】:

遗憾的是,我不能使用 C++ 中的任何 / 库,因为我正在为嵌入式操作系统编程,该操作系统只有可用的 4.4.4 和裸 C++,所以,没有 std::tuplestd::forwardstd::applystd::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( &amp;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...

但是让我们假设我不能这样做,因为该列表是从我无法控制的第三方输入的。如何在不使用任何标准库函数的情况下将参数包&lt;5, 1, 0&gt; 反转为&lt;0, 1, 5&gt;

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

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?

【问题讨论】:

    标签: stl std gcc clang template-meta-programming metaprogramming clang c++ c++11 metaprogramming variadic-templates template-meta-programming


    【解决方案1】:

    如何在不使用任何标准库函数的情况下将参数pack &lt;5, 1, 0&gt; 反转为&lt;0, 1, 5&gt;

    不确定您到底可以使用什么,但……对我来说似乎很容易。

    给定一个辅助结构如下

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

    【讨论】:

      猜你喜欢
      • 2021-09-06
      • 2018-08-22
      • 1970-01-01
      • 2015-11-16
      • 1970-01-01
      • 1970-01-01
      • 2013-04-15
      • 2018-10-15
      • 2013-03-19
      相关资源
      最近更新 更多