是否可以建立一组模板化函数指针,而无需手动执行此操作的麻烦?这是一个例子来说明我到底在说什么。
假设我有一个经常调用的函数“write”,我有两个实现(write0 和 write1),我希望能够在它们之间动态切换。这些写入函数是根据参数类型进行模板化的。实现此目的的一种方法是仅使用一个模板化前端函数 write(),它在内部使用 if 语句。
事实证明这足够快满足我的需求,但现在我想知道是否可以使用函数指针做同样的事情(只是为了好玩)。这种方法的问题是设置函数指针很麻烦。有没有其他方法可以本质上实现 write() 的理想但没有条件(直接静态调度)?
(其他“规则”:我无法更改 Msg 类以具有 write() 方法,并且无法更改使用站点代码以将 Msgs 替换为 Msgs 适配器。)
FWIW,我发现this article基本上我在这里说的是同样的事情。
#include <iostream>
using namespace std;
template<typename T> void write0(T msg) { cout << "write0: " << msg.name() << endl; }
template<typename T> void write1(T msg) { cout << "write1: " << msg.name() << endl; }
// This isn't so bad, since it's just a conditional (which the processor will
// likely predict correctly most of the time).
bool use_write0;
template<typename T> void write(T msg) { if (use_write0) write0(msg); else write1(msg); }
struct MsgA { const char *name() { return "MsgA"; } };
struct MsgB { const char *name() { return "MsgB"; } };
struct MsgC { const char *name() { return "MsgC"; } };
struct MsgD { const char *name() { return "MsgD"; } };
// This doesn't work: templates may not be virtual.
#if 0
struct Writer { template<typename T> virtual void write(T msg) = 0; };
struct Writer0 { template<typename T> virtual void write(T msg) { cout << "write0: " << msg.name() << endl; } };
struct Writer1 { template<typename T> virtual void write(T msg) { cout << "write0: " << msg.name() << endl; } };
#endif
int main(int argc, char **argv) {
use_write0 = argc == 1;
// I can do this:
write(MsgA());
// Can I achieve the following without the verbosity (manual setup, named
// template instantiations, etc.)?
void (*pwriteA)(MsgA) = use_write0 ? (void(*)(MsgA)) write0<MsgA> : (void(*)(MsgA)) write1<MsgA>;
void (*pwriteB)(MsgB) = use_write0 ? (void(*)(MsgB)) write0<MsgB> : (void(*)(MsgB)) write1<MsgB>;
void (*pwriteC)(MsgC) = use_write0 ? (void(*)(MsgC)) write0<MsgC> : (void(*)(MsgC)) write1<MsgC>;
void (*pwriteD)(MsgD) = use_write0 ? (void(*)(MsgD)) write0<MsgD> : (void(*)(MsgD)) write1<MsgD>;
pwriteA(MsgA());
pwriteB(MsgB());
pwriteC(MsgC());
pwriteD(MsgD());
return 0;
}
最佳答案
如果你想在程序运行时来回切换日志函数,我认为你必须手动设置每种类型的函数指针。
如果在启动时选择日志函数就足够了,那么它可以以完全通用的方式完成,甚至不需要知道稍后将调用该函数的类型:
// writer functions
template<typename T> void write0(T msg) { std::cout << 0; };
template<typename T> void write1(T msg) { std::cout << 1; };
// global flag
bool use_write0;
// function pointers for all types
template<typename T>
struct dispatch {
typedef void (*write_t)(T);
static write_t ptr;
};
// main write function
template<typename T>
inline void write(T msg) {
(*dispatch<T>::ptr)(msg);
}
// the fun part
template<typename T>
void autoinit(T msg) {
if (use_write0)
dispatch<T>::ptr = &write0<T>;
else
dispatch<T>::ptr = &write1<T>;
// call again for dispatch to correct function
write(msg);
}
// initialization
template<typename T>
typename dispatch<T>::write_t dispatch<T>::ptr = &autoinit<T>;
// usage example
int main(int argc, char **argv) {
use_write0 = (argc == 1);
write("abc");
return 0;
}
对于每种类型T
第一次调用write<T>()
决定应使用哪个写入功能。稍后的调用则直接使用指向该函数的函数指针。
关于c++ - 还有什么办法可以实现 "templated function pointers"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/560322/