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

如何在编译期生成std::bind值的std::initializer_list?

编译期生成含std::bind的std::initializer_list解决方案

问题描述

尝试通过模板函数在编译期创建包含std::bind值的std::initializer_list,但未能正确实现,原代码如下:

template<class T, int N> auto b(T t) -> auto
{
    if constexpr (N == 0) {
        return std::initializer_list<????????>{ std::bind(t, 0) };
    }
    else {
        return std::initializer_list { b<decltype(t), N-1>(t), std::bind(t, 0) };
    }
}

需求是避免编写重复的std::bind代码,比如:

char F(int c) { return 42; /* 实际会用c做相应操作 */ }
// ....
auto fs = { std::bind(F, 0), 
    std::bind(F, 1), 
    std::bind(F, 2), 
    std::bind(F, 3),
    std::bind(F, 4), 
    std::bind(F, 5) /* 等等...*/};

核心问题

原思路的根本问题在于:std::initializer_list无法通过递归拼接构造——它底层依赖临时数组,递归返回的initializer_list指向的临时对象会在函数返回后销毁,且语法上不支持将一个initializer_list与单个元素直接组合成新的initializer_list。

可行解决方案

方法一:利用编译期索引序列(推荐)

借助C++11引入的std::index_sequence生成编译期索引,一次性构造所有std::bind对象:

#include <functional>
#include <utility>

template<class Func, std::size_t... Is>
auto make_bind_list_impl(Func func, std::index_sequence<Is...>) {
    using BindType = std::decay_t<decltype(std::bind(func, 0))>;
    return std::initializer_list<BindType>{ std::bind(func, Is)... };
}

template<class Func, std::size_t N>
auto make_bind_list(Func func) {
    return make_bind_list_impl(func, std::make_index_sequence<N>{});
}

使用示例:

char F(int c) { return 42 + c; }

int main() {
    // 生成包含F绑定0到5的initializer_list(共6个元素)
    auto fs = make_bind_list<decltype(F), 6>(F);
    for (const auto& f : fs) {
        f(); // 调用每个绑定的函数
    }
}

该方法直接通过编译期序列展开构造对象,无生命周期问题,代码简洁高效。

方法二:模板递归生成索引序列

若不想依赖std::index_sequence,可通过模板递归生成索引,再展开构造:

#include <functional>

template<class Func, int N, int... Is>
struct BindListHelper {
    static auto create(Func func) {
        return BindListHelper<Func, N-1, N-1, Is...>::create(func);
    }
};

template<class Func, int... Is>
struct BindListHelper<Func, 0, Is...> {
    using BindType = std::decay_t<decltype(std::bind(func, 0))>;
    static auto create(Func func) {
        return std::initializer_list<BindType>{ std::bind(func, Is)... };
    }
};

template<class Func, int N>
auto make_bind_list(Func func) {
    return BindListHelper<Func, N>::create(func);
}

使用方式与方法一完全一致,本质是手动实现索引序列的生成逻辑。

关键注意事项

  • std::bind返回的是未指定类型,需用std::decay_t<decltype(std::bind(func, 0))>推导正确的类型作为initializer_list的模板参数。
  • 禁止递归拼接initializer_list,否则会导致临时数组销毁后的悬空引用问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 08:35:22