C++17中如何将传入模板函数的Lambda调用内联?
问题
我希望实现一个模板方法,该方法接收数据并通过Lambda函数对其进行处理。但我希望Lambda函数能够被内联,使得编译后的汇编代码中不会出现call指令。这是否可行?
如果使用Lambda无法实现,是否有其他方法?比如通过模板传递函数类型之类的方式?
我使用的是C++17。
现有示例代码:
template <typename T> static inline void Process(const T* p_source1, const T* p_source2, T* p_destination, const int count, std::function<T (T, T)> processor) { for (int i = 0; i < count; i++) p_destination[i] = processor(p_source1[i], p_source2[i]); } void Process_Add(const uint8_t* p_source1, const uint8_t* p_source2, uint8_t* p_destination, const int count) { // 如何让这个Lambda被内联? auto lambda = [] (uint8_t a, uint8_t b) { return a + b; }; Process<uint8_t>(p_source1, p_source2, p_destination, count, lambda); }
解答
你的核心问题在于使用了std::function——它是一个类型擦除的函数包装器,会引入间接调用(通常是通过虚函数表或函数指针),编译器几乎无法将这种间接调用内联,所以必然会产生call指令。
要实现Lambda的完全内联,最直接的方案是将处理器作为模板参数传递,而不是用std::function。这样编译器可以在实例化模板时直接看到Lambda的具体实现,从而完成内联优化。
修改后的代码如下:
// 将processor改为模板参数,而非函数参数 template <typename T, typename Processor> static inline void Process(const T* p_source1, const T* p_source2, T* p_destination, const int count, Processor processor) { for (int i = 0; i < count; i++) p_destination[i] = processor(p_source1[i], p_source2[i]); } void Process_Add(const uint8_t* p_source1, const uint8_t* p_source2, uint8_t* p_destination, const int count) { // 直接传递Lambda,C++17会自动推导Processor模板参数 Process(p_source1, p_source2, p_destination, count, [] (uint8_t a, uint8_t b) { return a + b; }); }
为什么这样能实现内联?
每个Lambda表达式都会生成一个唯一的匿名类型,当它作为模板参数传递时,编译器会为这个特定的Lambda类型实例化Process模板。此时编译器完全可见Lambda的函数体,能够直接将Lambda的逻辑嵌入到循环中,彻底消除call指令。
其他可选方案
- 函数指针:如果处理器是普通函数而非Lambda,可以传递函数指针,但编译器对函数指针的内联优化远不如模板参数(因为函数指针的目标在编译时可能无法确定)。
- 仿函数(Functor):手动定义一个重载
operator()的结构体,效果和Lambda作为模板参数类似,但写法更繁琐。
需要注意的是,要确保编译器开启了优化选项(比如-O2或/O2),否则即使代码结构正确,编译器也不会进行内联。
内容的提问来源于stack exchange,提问作者user19179144
相关产品推荐
相关产品推荐

