采用函数指针的函数模板的干净实现
Clean implementation of function template taking function pointer
我已经设法实现并测试了我的函数包装器实现,但是,界面并不像它应该的那样好:
template < typename F, F* f >
void register_function( const char* name )
{
int (*lf) (lua_State *) = function_wrapper< F, f >;
register_native_function( lf, name );
}
虽然这按预期工作,但用法需要显式模板参数:
register_function< decltype(hello), &hello >( "hello" );
显然,第一个参数可以从第一个参数中推导出来,所以理想情况下我只想拥有
register_function< &hello >( "hello" );
可能吗?有没有更整洁的方法?
更新:回答问题,为什么参数是模板化的而不是传递的:
许多绑定器(包括 Lua 绑定器,因为它是专门为 Lua 设计的)按值传递函数:
register_function("hello", &hello);
这确实更具可读性,并且从界面端更容易实现。但这也意味着函数的地址需要存储在某个地方。
要将函数绑定到 Lua,我们需要它具有以下原型:
int (*lua_CFunction) (lua_State *)
没有传递其他信息,因此这是我们从Lua调用绑定函数时获得的条目和信息。
如果绑定是在编译时完成的,我们可以在将从 Lua 执行的代码中提供一个单独的函数(通过模板),为我们提供与手写绑定相当的性能,尤其是在编译器优化样板代码的情况下。
如果绑定是在运行时完成的,那么我们就不能创建新函数,需要一个全局函数,该函数以某种方式知道它应该将调用调度到哪个函数。通常,我们根本无法获取信息,但现有的编译时 Lua 绑定器利用 Lua 自定义的每函数用户数据或闭包来存储执行执行所需的其他信息。但是,与手写绑定相比,这在性能上有很大的影响,因为可能会有额外的内存分配和闭包调度。
我在以前的绑定实现(尽管压力很大)中遇到了运行时版本的性能问题,最终将压力最大的部分重写为手写绑定,并且考虑到这次我计划在实时渲染循环中进行 lua 调用,我想找到一种更接近手写性能的解决方案。
如果我们将函数作为参数传递,显然无法在编译时创建函数绑定。
对不起,戴夫,你不能那样做。
有人提议在模板类型列表的后面从文本类型中推导出模板类型。 最后我检查了一下,它不会进入 C++1y(又名 C++14)。
宏可能会有所帮助,直到语言添加该功能:
#define REGFUNC( F ) decltype(F), (F)
register_function< REGFUNC(hello) >( "hello" );
也有人谈论在C++中添加"lambda to C 函数"支持(能够获取有状态的 lambda,并要求它生成一个 C 函数,该函数将使用该状态调用它),但我不知道进展如何。
将此问题的六年年龄添加到标记的语言版本中:C++17 允许使用占位符声明模板参数。
template < auto &F >
void register_function( const char* name )
{
int (*lf) (lua_State *) = function_wrapper< std::remove_reference_t<decltype(F)>, F >;
register_native_function( lf, name );
}
这对于函数特别有用,因为概念类型"可调用"实际上是许多C++类型。 (使用引用有助于避免像register_function<2>("?!")
这样的愚蠢事情。
- 当函数模板参数是具有默认参数的类模板时,函数模板参数的推导如何执行
- 将重载的成员函数传递给函数模板
- C++17中函数模板中的静态数组初始化(MSVC 2019)
- 为什么 gcc 和 clang 为函数模板的实例化生成不同的符号名称?
- 基于 SFINAE 的特征实现问题与函数模板重载
- 为什么'std::array::at()'没有实现为模板函数?
- 通过模板滥用实现函数式C++
- Pimpl 习语实现取决于模板函数
- C++——我可以使用一个没有在头文件中实现的模板函数吗
- 使用成员函数模板实现接口的功能
- C++ 对代码中实现和模板化的函数的未定义引用
- 实现函数模板填充多维对象
- 采用函数指针的函数模板的干净实现
- 为容器的元素实现一个模板函数,总和为C++
- 用shared_ptrs实现函数模板的C++实例化
- 成员函数的实现取决于模板参数
- 关于实现静态成员函数模板时重定义错误的c++问题
- 使用c++函数模板实现一组函数
- C++ 使用无法更改的通用参考函数模板实现过载分辨率
- 实现一个模板函数,该函数接受两个类作为模板参数,如果它们被继承则返回true