Aar*_*man 6 c++ templates c++11 argument-deduction
这个问题非常类似于:" 从decltype(someFunction)中提取参数类型列表 ".我不确定那里的答案是否符合我的意图.我希望能够创建一个模板函数,该函数根据函数指针模板参数(whistles)的类型推断出其运行时参数的类型.
对于一个示例用例,假设我想使用加载了LD_PRELOAD的填充库来直接测量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 ...
}
Run Code Online (Sandbox Code Playgroud)
我们可以使用可变参数模板函数保存一些代码:
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);
}
Run Code Online (Sandbox Code Playgroud)
我们可以通过某种方式避免在模板参数列表中传递所有这些冗余类型.我想做什么,我还没有找到有效的语法(假设存在我称之为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);
}
Run Code Online (Sandbox Code Playgroud)
在C++ 11,14或17中有没有一种有效的方法呢?如何,如果没有,为什么不呢?
你使用部分专业化:
template <typename func_ptr_type, func_ptr_type real_func_ptr,
const char *dl_name>
struct Wrapper;
template <typename Ret, typename... Args, Ret (*real_func_ptr)(Args...),
const char *dl_name>
struct Wrapper<Ret(*)(Args...), real_func_ptr, dl_name>
{
static Ret func(Args... args) { /* ... */ }
};
Run Code Online (Sandbox Code Playgroud)
皱纹是因为你不能部分专门化你需要使用类模板的函数 - 这里Wrapper
.