C++11 可变模板函数的显式实例化

C++11 可变模板函数的显式实例化,c++11,code-generation,instantiation,variadic-templates,C++11,Code Generation,Instantiation,Variadic Templates,我正在编写一个使用可变模板函数的库,如下所示: template<typename ... T> void func(T ... args) { // ... } template class func<int>; template class func<int, int>; template class func<int, int, int>; // ... 但是,编译器对于函数生成递归没有合适的基本情况,因此无法编译。我还尝试过使用非类

我正在编写一个使用可变模板函数的库,如下所示:

template<typename ... T>
void func(T ... args) {
  // ...
}
template class func<int>;
template class func<int, int>;
template class func<int, int, int>;
// ...
但是,编译器对于函数生成递归没有合适的基本情况,因此无法编译。我还尝试过使用非类型模板,例如(使用以下代码):

template struct seq{};
模板结构gens:gens{};
模板结构gens{typedef seq type;};
std::向量参数;
模板
无效f(序号){
测试(标准:获取(参数)…);
}
无效实例化(最大大小){
对于(int i=1;i

但这需要一个const值,因此它也无法编译。在不知道
maxArgs()
的返回值的情况下,是否有任何方法可以正确执行此操作?

否,您不可能在编译时生成依赖于仅在运行时已知的值的模板。您需要提前选择一个常量的最大值(有时不使用所有的实例化),或者找到一种方法使maxArgs()成为编译时常量。或者在使用时动态编译代码


因为你比我们有更多关于这段代码的信息,也许你可以考虑是否需要把它变成一个可变的模板。考虑到模板参数的数量是在运行时确定的,所以很可能不是这样。最好编写一个完全由运行时决定的解决方案,而不使用可变模板。

因为我知道
maxArgs()
(即42)有一个最大可能的值,所以我根据@JohnZwinck的建议提出了以下解决方案

#include <vector>

typedef void (*void_fnptr)();

std::vector<void_fnptr> table;

// Function that needs to be code-generated for certain number of int types
template<typename ... T>
void func(T ... args) {
  // ...
}

template<typename T>
void instantiate(T elem) {
  table.push_back((void_fnptr)func<T>);
}

template<typename T, typename ... Ts>
void instantiate(T first, Ts ... rest) {
  table.push_back((void_fnptr)func<T, Ts...>);
  instantiate(rest...);
}

int main(int argc, char** argv) {
  // 42 int arguments:
  instantiate(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
              0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
  // ...
  return 0;
}
#包括
typedef void(*void_fnptr)();
std::向量表;
//需要为特定数量的int类型生成代码的函数
模板
无效函数(T…参数){
// ...
}
模板
无效实例化(T元素){
表.推回((无效)功能);
}
模板
void实例化(T优先,Ts…剩余){
表.推回((无效)功能);
实例化(rest…);
}
int main(int argc,字符**argv){
//42整型参数:
实例化(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
// ...
返回0;
}

因此,我需要以这种方式生成代码的原因是,我必须为另一个库提供
func
的各种实例的函数指针,而不知道使用我自己的库的应用程序将使用哪些特定实例。另外,我传递函数指针的库负责
maxArgs()
。maxArgs()的允许范围是多少?在如何给它函数指针方面,另一个库的确切要求是什么?它可以接受指向C风格变量函数(如printf)的指针,还是需要指向使用1..maxArgs参数的常规函数的指针?如果是后者,任何这样的图书馆如何被正确使用?这似乎很难想象。可能的范围是
8@AlexBrooks:那么你似乎应该为所有值实例化你的函数模板,最多42个,然后用它完成。如果库调用您的函数时,第一个参数是以下参数的数量,那么您可以编写一个非模板的printf样式的函数。就目前的情况而言,我对您使用的这个库的设计感到惊讶:它似乎是为了迷惑用户而设计的。谢谢。对于更多的上下文,库是GASNet,我描述的库的一部分是围绕其活动消息功能的包装器(出于各种原因)。考虑到这可能是不可能的,编译器(特别是gcc)如何使用省略号和va_列表处理C样式变量参数函数的代码生成?例如:
void func(int a,…{…}
template<int ...> struct seq { };
template<int N, int ... Ns> struct gens : gens<N-1, N-1, Ns...> { };
template<int ... Ns> struct gens<0, Ns...> { typedef seq<Ns...> type; };

std::vector<int> params;

template<int ... Ns>
void f(seq<Ns...>) {
  test(std::get<Ns>(params)...);
}

void instantiate(size_t max) {
  for (int i = 1; i < max; ++i) {
    for (int j = 0; j < i; ++j) {
      params.push_back(0);
    }
    f(typename gens<i>::type()); // Fails to compile -- i is not const
    params.clear();
  }
}

int main(int argc, char** argv) {
  instantiate(maxArgs());
}
#include <vector>

typedef void (*void_fnptr)();

std::vector<void_fnptr> table;

// Function that needs to be code-generated for certain number of int types
template<typename ... T>
void func(T ... args) {
  // ...
}

template<typename T>
void instantiate(T elem) {
  table.push_back((void_fnptr)func<T>);
}

template<typename T, typename ... Ts>
void instantiate(T first, Ts ... rest) {
  table.push_back((void_fnptr)func<T, Ts...>);
  instantiate(rest...);
}

int main(int argc, char** argv) {
  // 42 int arguments:
  instantiate(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
              0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
  // ...
  return 0;
}