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