You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++中实现类似Java Supplier的未求值表达式传参?

在C++中实现类似Java Supplier的延迟求值功能

Java里的Supplier核心是延迟求值——只有在需要的时候才执行表达式并返回结果。在C++里有几种等价实现方式,各有优劣:

1. 使用std::function(最接近Java Supplier的写法)

std::function<Foo()>是C++的通用可调用对象包装器,和Java的Supplier<Foo>语义几乎一致。调用时用lambda表达式传入延迟执行的逻辑,通过()运算符触发求值。

代码示例

#include <functional>

// 假设Foo是已定义的类
class Foo {};

void doSomething(std::function<Foo()> supplier, bool gonnaNeedThatObject) {
    if (gonnaNeedThatObject) {
        Foo foo = supplier();
        // 在这里处理foo
    }
}

int main() {
    // 传入lambda表达式,仅在supplier()被调用时才执行Foo的构造
    doSomething([]() { return Foo(); }, true);
    return 0;
}

优点:类型安全,支持所有可调用对象(lambda、普通函数、成员函数绑定对象等),灵活性拉满。
缺点:基于类型擦除实现,会有轻微的运行时开销。

2. 使用模板参数(极致性能选择)

把可调用对象作为模板参数传入,编译器会在编译期做完全优化,消除任何运行时开销。

代码示例

class Foo {};

template<typename Supplier>
void doSomething(Supplier supplier, bool gonnaNeedThatObject) {
    if (gonnaNeedThatObject) {
        Foo foo = supplier();
        // 处理foo的逻辑
    }
}

int main() {
    doSomething([]() { return Foo(); }, false);
    return 0;
}

优点:零运行时开销,性能最优,同样支持所有可调用类型。
缺点:不同的可调用对象类型会触发函数的重复实例化,可能增加二进制体积;若为头文件中的模板函数,需注意编译依赖问题。

3. 使用函数指针(仅适用于无状态调用)

如果延迟逻辑不需要捕获外部变量(比如普通函数、无捕获lambda),可以直接用函数指针作为参数,完全没有额外开销。

代码示例

class Foo {};

// 普通函数作为延迟求值逻辑
Foo createFoo() {
    return Foo();
}

void doSomething(Foo(*supplier)(), bool gonnaNeedThatObject) {
    if (gonnaNeedThatObject) {
        Foo foo = supplier();
        // 处理foo
    }
}

int main() {
    // 传入普通函数指针
    doSomething(&createFoo, true);
    // 无捕获lambda可以隐式转换为函数指针
    doSomething([]() { return Foo(); }, false);
    return 0;
}

优点:完全没有运行时开销,语法简单直接。
缺点:只能接受无捕获的可调用对象,无法捕获外部变量,灵活性极差。

方法选择总结

  • 优先选std::function:大多数场景下的平衡之选,灵活性足够,开销可忽略。
  • 追求性能选模板参数:适合对性能敏感的底层代码,能接受模板实例化的代价。
  • 简单无状态逻辑选函数指针:仅在确定不需要捕获外部变量时使用。

内容的提问来源于stack exchange,提问作者H.v.M.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 20:50:08