我想将派生类的可变参数模板参数(一组整数)传递给另一个模板化类。 我不能修改第二个类,因为它是一个库的一部分。
我已经弄清楚了如何在编译时存储该参数(例如常量数组或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;
}
答案 0 :(得分:5)
您可以编写一个辅助函数,将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()>{});
}
还请注意,保留以下划线后跟大写字母开头的标识符。它们的用法导致未定义的行为。不要使用它们。
答案 1 :(得分: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();