C++中内联函数包装器的限制
Limits to inlining function wrappers in C++
我的问题涉及C++中函数包装器的内联优化应用,请考虑以下代码,WorkerStructure对象是用封装一些功能块的函数包装器初始化的。然后在调用WorkerStructure::doSomeWork方法时使用函数包装器。
workerFunction对象封装的功能在WorkerStructure::doSomeWork方法上应用时是否会内联?,显然,如果该功能是在其他转换单元中定义的,workerFunction对象只封装了一个函数指针,那么是否存在其他无法内联的情况
当在不同的转换单元中定义的lambda函数通过函数包装器传递时,它是否等效于传递函数指针?
struct WorkerStructure
{
WorkerStructure(std::function <bool(float)> &f):workerFunction(f) {}
void doSomeWork(float inputValue)
{
if(workerFunction(inputValue))
{
//do some conditional operation
}
}
std::function <bool(float)> workerFunction ;
};
std::function
的多态性本质上使实际内联调用变得非常困难。由于CCD_ 2可以报道任何可调用实体;您将如何编写内联代码?
这有点像内联虚拟函数,这些函数是在没有其他可用信息的情况下通过基指针调用的(也就是说,在调用之前没有从派生到基指针的赋值,编译器可能会使用它来启用内联)。
大多数情况下,std::function
是用一个void*
指针和一个指向模板化函数专门化的函数指针来实现的,该函数执行实际的调用和强制转换等操作。当然,也有一些变体使用虚拟函数来实现这一点,它们更清楚地说明了为什么这非常困难。即使是链接时间的阿片化也无能为力,因为这无关紧要,你已经拥有了在呼叫站点上可以获得的所有信息(这并不多)。
以下是std::function
的非常的粗略版本,使用指向模板的指针函数版本,只处理存储和调用方面(忽略内存管理、复制、移动、重置、空间优化等):
template<class Sig>
class function;
template<class R, class... Args>
class function<R(Args...)>{
typedef R (*call_type)(void*, Args...);
void* _obj;
call_type _caller;
public:
template<class F>
function(F f)
: _obj(new F(f))
, _caller([](void* p, Args... args){ return (*static_cast<F*>(p))(args...); })
{}
R operator()(Args... args) const{
return _caller(_obj, args...);
}
};
活生生的例子。我认为很难检查_obj
和_caller
内部的实际内容以及调用function
的点。
这里是带有虚拟函数的版本,仅供参考。
std::function
的动态特性使它本质上是一个虚拟调用,因为virtual
调用只不过是指向函数的指针。
以LLVM为例,让我们玩以下程序:
#include <cstdio>
typedef void (*Function)();
void donothing() {}
void print() { printf("Hello World!"); }
Function get(int i) {
if (i % 2 == 0) { return donothing; }
return print;
}
int main() {
Function f = get(0);
f();
}
发射的主要功能:
define i32 @main() uwtable readnone {
ret i32 0
}
因此,编译器能够理解哪个函数被选中(通过内联和常量传播的组合),并内联调用。
不幸的是,我在电子邮件中证明了通过虚拟表传递是不起作用的(优化器不知何故丢失了信息,无法内联调用)。因此,尽管内联完全有可能通过std::function
工作,但它可能不仅取决于编译器,还取决于您碰巧使用的std::function
的特定实现。恐怕您需要试用您的应用程序。
- 我的包装函数缺少变量?
- 为什么这个"ctypes"包装函数的返回值是"c_long(0)"而不是&quo
- 如何将包装类的对象用作包装函数中的参数
- 包装C++函数以使用 SWIG 获取 Lua 字符串表
- 带有默认参数的宏包装函数调用
- 如何使用模板函数参数编写包装函数,该功能可以采用超载的成员函数
- 创建一个__cdecl以在 C++ 上__thiscall包装函数
- 在C++中实现和包装函数组合以进行惰性计算
- c++11:如何编写一个包装函数来生成"std::function"对象
- 为什么 Dart 中的原生包装函数与非常轻量级的函数相比"DEFINE NATIVE ENTRY"如此重量级?
- 在 C++ 中使用 map,并提供包装函数以在 C 语言中使用它
- 包装函数只有在链接为静态时才从链接库调用
- 尝试包装函数返回值时出现"<类名>不提供调用运算符"错误
- 交叉编译器/平台裸包装函数,无条件跳转到函数指针
- realloc C 函数的可能包装函数有什么错误?
- 包装 C++ 函数以在 C# 中使用
- 采用"pass by reference"值的递归函数的包装函数
- C++包装函数(宏)来访问 COM 对象属性
- 包装函数指针和函数对象在泛型代码中是如何工作的
- 在c++类中直接包装函数