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

能否使用std::bind*实现C++20函数组合?

用std::bind*重构C++20函数组合的compose函数问题

我正在C++20中尝试函数式编程,已基于Lambda实现了函数组合逻辑,但希望改用std::bind*重构双参数compose函数。我认为std::bind_front的写法比Lambda更简洁,尤其是针对无重载运算符的函数。目前的问题是无法正确传递可变参数给内部函数,尝试过类比单参数场景的写法变体但均失败,想了解可行实现方案或无法实现的原因。

已实现的Lambda版本代码

template <class OuterFn, class InnerFn, class... Args>
concept Composable =
    std::invocable<OuterFn, std::invoke_result_t<InnerFn, Args...>>;

template <class OuterFn, class InnerFn>
constexpr auto
compose(OuterFn&& outer, InnerFn&& inner)
{
    return [
        out = std::forward<OuterFn>(outer),
        in = std::forward<InnerFn>(inner)
    ]<class... Args>(Args && ... args)
        requires Composable<OuterFn, InnerFn, Args...>
    {
        using std::invoke, std::forward;
        return invoke(out, invoke(in, forward<Args>(args)...));
    };
}

template <class OuterFn, class InnerFn>
constexpr auto
operator*(OuterFn&& outer, InnerFn&& inner)
{
    using std::forward;
    return compose(forward<OuterFn>(outer), forward<InnerFn>(inner));
}

template <class... RestFn>
constexpr auto
compose(RestFn&&... rest)
{
    return (std::forward<RestFn>(rest) * ...);
}

示例对比

  • 使用std::bind_front的写法:
using eq_t = std::equal_to<const std::string_view>;
constexpr auto eq_42 = std::bind_front(eq_t{}, "42");
  • Lambda写法:
constexpr auto eq_42 = [](const std::string_view sv){ return sv == "42"; };

尝试过的无效写法

std::bind(outer, std::bind_front(inner));


解决方案与分析

为什么直接用std::bind无法实现可变参数的函数组合

std::bind依赖固定的占位符(std::placeholders::_1、std::placeholders::_2等)转发参数,但这些占位符是预定义的固定数量,无法支持任意数量的可变参数Args...。当你写std::bind(outer, std::bind_front(inner))时,内部的bind_front(inner)需要接收参数,但std::bind不会自动将后续传入的所有参数转发给它,除非显式指定占位符——但没法为任意数量的参数生成对应的占位符。

有限参数场景的bind实现(仅作示例)

如果只需要支持固定数量的参数,比如单参数,可以这样写:

template <class OuterFn, class InnerFn>
constexpr auto compose_bind(OuterFn&& outer, InnerFn&& inner) {
    return std::bind(
        std::forward<OuterFn>(outer),
        std::bind(std::forward<InnerFn>(inner), std::placeholders::_1)
    );
}

但这种写法无法扩展到任意数量的可变参数,因为你无法提前知道需要多少个占位符。

结论:Lambda仍是通用函数组合的最优选择

std::bind*系列工具更适合绑定固定数量的参数到函数/函数对象,而通用的函数组合需要处理任意数量的可变参数转发,Lambda的模板参数包Args...可以完美适配这种场景,实现简洁且类型安全的参数转发。

如果一定要用std::bind实现可变参数的函数组合,你需要自己实现一套可变占位符的生成逻辑,这会大幅增加代码复杂度,反而失去了std::bind原本的简洁性,完全不如Lambda版本实用。

内容的提问来源于stack exchange,提问作者hlebyshek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 03:11:14