【问题标题】:How to store variadic template parameters in c++ ?如何在 C++ 中存储可变参数模板参数?
【发布时间】:2019-03-29 21:44:54
【问题描述】:

我想将派生类的可变参数模板参数(一组整数)传递给另一个模板类。 我不能修改第二个类,因为它是库的一部分。

我已经想出了如何在编译时存储这些参数(例如常量数组或 integer_sequence),但我不知道如何将这些结构传递给库类。 解决方案可能很明显,但我目前迷失了处理这些可变参数的所有可能性。

我尝试构建一个简单的示例来更好地解释我的问题:

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

【问题讨论】:

  • 你知道你的代码中有很多多余的;,对吧?

标签: c++ variadic-templates


【解决方案1】:

你可以创建助手来做到这一点:

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;

然后

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

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

【讨论】:

    【解决方案2】:

    你可以编写一个解包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{});
    }
    

    然后像这样使用它:

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

    你可以为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()>{});
    }
    

    另请注意,以下划线后跟大写字母开头的标识符是保留的。它们的使用会导致未定义的行为。不要使用它们。

    【讨论】:

      猜你喜欢
      • 2013-05-27
      • 1970-01-01
      • 2016-12-01
      • 1970-01-01
      • 2012-12-29
      • 1970-01-01
      • 2017-08-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多