简体   繁体   English

如何在c ++中存储可变参数模板参数?

[英]How to store variadic template parameters in c++ ?

I want to pass the variadic template parameters (a set of integers) of an derived class to another templated class. 我想将派生类的可变参数模板参数(一组整数)传递给另一个模板化类。 I can not modify the second class because its part of an libary. 我无法修改第二个类,因为它是libary的一部分。

I already figured out how I can store this parameters at compile time (eg constant array or integer_sequence) but I have no clue how to pass these structures to the library class. 我已经弄清楚如何在编译时存储这些参数(例如常量数组或整数序列),但我不知道如何将这些结构传递给库类。 The solution might be obvious but I'm currently lost in all the possibilities to handle this variadic stuff. 解决方案可能很明显但我现在已经失去了处理这种可变参数的所有可能性。

I tried to build a simple example to explain my problem better: 我试图建立一个简单的例子来更好地解释我的问题:

// Example program
#include <iostream>
#include <array>
#include <utility>


// this class has some compile time paramters
template <int... N>
class BaseClass
{
  public:
  BaseClass(){};
  ~BaseClass(){};

   //one idea to store the parameters using a compile time array 
   static constexpr std::array<int, sizeof...(N)> _N = {{N...}};

   //another idea using a integer sequence type
   using _Ni = std::integer_sequence<int, N...>;
};

// this special case of BaseClass hast the parameter 5,6,7,8
class SpecialClass:public BaseClass<5,6,7,8>
{
  public:
  SpecialClass(){};
  ~SpecialClass(){};
};


// this class is fixed and can not be modified because it's part of an libary
template <int... N>
class Printer
{
    public:
    Printer(){};
    ~Printer(){};

    // it can (for example) print its template parameters
    void print()
    {
        int dummy[sizeof...(N)] = { (std::cout << N, 0)... };
    }
};


int main()
{

  // this obviously works
  Printer <1,2,3,4> TestPrinter;
  TestPrinter.print();

  // this works not
  Printer <SpecialClass::_N> TestPrinterSpecialArray;
  TestPrinterSpecialArray.print();

  // this also works not
  Printer <SpecialClass::_Ni> TestPrinterSpecialSequence;
  TestPrinterSpecialSequence.print();

  return 0;
}

You can write a helper function that unpacks std::integer_sequence , 你可以编写一个解包std::integer_sequence的辅助函数,

template<int... is>
auto make_printer_impl(std::integer_sequence<int, is...>)
{
    Printer<is...> printer;
    return printer;
}

template<class T>
auto make_printer()
{
    return make_printer_impl(typename T::_Ni{});
}

and then use it like this: 然后像这样使用它:

auto TestPrinterSpecialSequence = make_printer<SpecialClass>();
TestPrinterSpecialSequence.print();

You can do the similar thing for std::array member: 你可以为std::array成员做类似的事情:

template<class T, std::size_t... is>
auto make_printer_impl(std::index_sequence<is...>)
{
    Printer<T::_N[is]...> printer;
    return printer;
}

template<class T>
auto make_printer()
{
    return make_printer_impl<T>(std::make_index_sequence<T::_N.size()>{});
}

Also note that identifiers that begin with an underscore followed by an uppercase letter are reserved. 另请注意,保留以下划线后跟大写字母开头的标识符。 Their usage leads to the undefined behavior. 它们的使用会导致未定义的行为。 Don't use them. 不要使用它们。

You can create helper to do that: 您可以创建帮助程序来执行此操作:

template <typename T, template <std::size_t...> class Other> struct remap;

template <template <std::size_t...> class Orig,
          std::size_t... Is,
          template <std::size_t...> class Other>
struct remap<Orig<Is...>, Other>
{
    using type = Other<Is...>;
};

template <typename T, template <std::size_t...> class Other>
using remap_t = typename remap<T, Other>::type;

And then 接着

using SpecialClass = BaseClass<5,6,7,8>;

remap_t<SpecialClass, Printer> TestPrinterSpecialSequence; // Printer <5, 6, 7, 8>
TestPrinterSpecialSequence.print();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM