这个问题非常类似于:“ Extract just the argument type list from decltype(someFunction) ”。我不确定那里的答案是否适用于我的意图。我希望能够创建一个模板函数,该函数根据函数指针模板参数(whistles)的类型推断其运行时参数的类型。
对于一个示例用例,假设我想使用加载了 LD_PRELOAD 的 shim 库来检测直接的 C POSIX 文件 I/O。我可以为 fopen、fread、fwrite、fclose 编写单独的包装器......如果所有这些包装器都做类似的事情,如果我可以定义一个捕获常见行为的模板,那不是很好吗?
不使用模板来演示涉及多少样板的部分示例:
extern "C" {
FILE *(*real_fopen)(const char *, const char *) = NULL;
FILE *fopen(const char *path, const char *mode)
{
FILE *returned_file;
if (real_fopen == NULL) {
real_fopen = ((FILE *)(const char *, const char *))dlsym("fopen", RTLD_NEXT);
}
... do pre-call instrumentation ...
returned_file = real_fopen(path, mode);
... do post-call instrumentation ...
return returned_file;
}
int (*real_fclose)(FILE *) = NULL;
int fclose(FILE *fp)
{
int retval;
if (real_fclose == NULL) {
real_fclose = ((int)(FILE *))dlsym("fclose", RTLD_NEXT);
}
... do pre-call instrumentation ...
retval = real_fclose(path, mode);
... do post-call instrumentation ...
return retval;
}
... additional definitions following the same general idea ...
}
我们可以使用可变参数模板函数保存一些代码:
template <typename func_ptr_type, func_ptr_type real_func_ptr,
const char *dl_name, typename... Args>
std::result_of<func_type> wrap_func(Args... args)
{
std::result_of<func_type> retval;
if (real_func_ptr == NULL) {
real_func_ptr = (func_ptr_type)dlsym(dl_name, RTLD_NEXT);
}
... do pre-call instrumentation ...
retval = real_func_ptr(args...);
... do post-call instrumentation ...
return retval;
}
FILE *(*real_fopen)(const char *, const char *) = NULL;
FILE *fopen(const char *path, const char *mode)
{
return wrap_func<decltype(real_fopen), real_fopen, "fopen", const char *, const char *>(path, mode);
}
int (*real_fclose)(FILE *) = NULL;
int fclose(FILE *fp)
{
return wrap_func<decltype(real_fclose), real_fclose, "fclose", FILE *>(fp);
}
不过,我们必须有某种方法可以避免在模板参数列表中传递所有这些冗余类型。我想做的事情是我还没有找到有效的语法(假设存在我称之为 std::arguments_of 的东西,有点像 std::result_of 的反面):
template <typename func_ptr_type, func_ptr_type real_func_ptr,
const char *dl_name, std::arguments_of(func_ptr_type)>
std::result_of<func_type> wrap_func(std::arguments_of(func_ptr_type)... args)
{
std::result_of<func_type> retval;
if (real_func_ptr == NULL) {
real_func_ptr = (func_ptr_type)dlsym(dl_name, RTLD_NEXT);
}
... do pre-call instrumentation ...
retval = real_func_ptr(args...);
... do post-call instrumentation ...
return retval;
}
FILE *(*real_fopen)(const char *, const char *) = NULL;
FILE *fopen(const char *path, const char *mode)
{
return wrap_func<decltype(real_fopen), real_fopen, "fopen">(path, mode);
}
int (*real_fclose)(FILE *) = NULL;
int fclose(FILE *fp)
{
return wrap_func<decltype(real_fclose), real_fclose, "fclose">(fp);
}
在 C++11、14 或 17 中是否有有效的方法来执行此操作?如何,或者如果不是,为什么不呢?