2014-09-06 80 views
3

我写一个使用可变参数为模板的功能,像这样一个图书馆:的可变参数模板显式实例化功能

template<typename ... T> 
void func(T ... args) { 
    // ... 
} 

我需要确保在该函数中生成的代码(即显式实例化)的某些类型,像这样:

template class func<int>; 
template class func<int, int>; 
template class func<int, int, int>; 
// ... 

其中int参数的最大数是一个非const maxArgs()(我无法改变这个,因为它是一个外部函数)。我试过以下内容:

template<typename ... T> 
void f(size_t max, T ... args) { // Generates "infinitely" 
    if (sizeof...(T) < max) { 
    func(args...); 
    f(max, args..., 0); 
    } 
} 

int main(int argc, char** argv) { 
    f(maxArgs(), 0); 
    // ... 
    return 0; 
} 

但是,编译器对函数生成递归没有适当的基本情况,所以无法编译。我已经使用非类型模板,像这样(使用一些代码here)也试过:

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

但这需要一个常量的值,所以无法编译为好。有没有办法正确地做到这一点,不知道maxArgs()的返回值?

+0

鉴于这可能是不可能的,编译器(特别是gcc)如何使用省略号和va_list处理C风格变量参数函数的代码生成?例如:'void func(int a,...){...}' – 2014-09-06 08:55:53

回答

0

因为我知道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; 
} 
1

不,您不可能在编译时生成取决于仅在运行时已知的值的模板。你需要选择一些预先保持不变的最大值(有时候不要使用所有的实例),或者想办法让maxArgs()成为编译时常量。或者在使用时即时编译您的代码!

由于您对此代码的信息比我们做得更多,因此您可能会考虑是否将其作为可变参数模板实际上是需要的。它似乎不是,因为模板参数的数量是在运行时确定的。编写一个完全运行时确定的解决方案可能会更好,但没有可变参数模板。

+0

所以我需要以这种方式生成代码的原因是我必须为另一个库提供各种实例的函数指针'func',不知道应用程序将使用我自己的库来使用哪些特定的实例。此外,我传递函数指针的库负责'maxArgs()'。 – 2014-09-06 08:46:40

+0

'maxArgs()'的允许范围是多少?根据您需要如何给它指定函数指针,其他库的确切要求是什么?它是否可以接受指向C风格可变参数函数的指针(如printf),还是需要指向常量函数的指针,取1..maxArgs参数?如果是后者,那么这样的图书馆如何被正确地使用?这似乎很难想象。 – 2014-09-06 09:00:17

+0

可能的范围是'8 <= maxArgs()<= 42'。该库以函数指针数组的形式获取函数,其中类型必须类型转换为void(* fn)()';这些函数不需要模板,并且可以使用C风格的可变参数函数 – 2014-09-06 14:21:03