如何反转整数参数包?

时间:2018-11-04 20:33:55

标签: c++ c++11 metaprogramming variadic-templates template-meta-programming

遗憾的是,我无法使用C ++的 / 库中的任何一个,因为我正在为嵌入式操作系统编程,而该操作系统仅具有裸露的可用 ViewPager C ++,因此没有4.4.4std::tuplestd::forwardstd::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;
}

参考文献:

  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 个答案:

答案 0 :(得分:2)

  

如何在不使用任何标准库函数的情况下将参数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; };

还原结构可以简单

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