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

关于std::array的lambda包展开初始化的三个技术疑问

运行时基于索引实例化std::variant的代码疑问解答

先给出这段可在C++17、GCC 8.5环境下正常运行的代码:

template <typename... Ts>
std::variant<Ts...> make_variant(std::size_t i)
{
    assert(i < sizeof...(Ts));
    static constexpr auto table = std::array{ +[](){ return std::variant<Ts...>{Ts{ }}; }...  };
    return table[i]();
}

针对代码中table数组初始化的疑问,解答如下:

1. 为何此处std::array未指定模板类型?

C++17引入了类模板实参推导(CTAD),编译器可以根据初始化列表的内容自动推导std::array的模板参数。这里初始化列表里的每个元素都是相同类型的函数指针(经过+转换后的lambda指针),编译器能自动推导出std::array的元素类型和大小,因此不需要显式指定std::array<FuncPtr, sizeof...(Ts)>。

2. lambda表达式前的+有何作用?

无捕获的lambda表达式可以隐式转换为对应的函数指针,但lambda本身是匿名闭包类型,直接放入std::array初始化列表时,编译器可能无法自动完成转换。加上+运算符后,会触发lambda到函数指针的隐式转换,将其转换成std::variant<Ts...>(*)()类型的函数指针,确保所有元素类型一致,能被std::array正确容纳。

3. 该折叠表达式的工作原理是什么?

这里的...是C++17的折叠表达式,用于将模板参数包Ts...展开为多个元素。具体来说,+[](){ return std::variant<Ts...>{Ts{ }}; }...会被展开为:

+[](){ return std::variant<Ts1, Ts2, ..., Tsn>{Ts1{ }}; },
+[](){ return std::variant<Ts1, Ts2, ..., Tsn>{Ts2{ }}; },
...
+[](){ return std::variant<Ts1, Ts2, ..., Tsn>{Tsn{ }}; }

每个展开后的lambda函数负责创建对应类型的std::variant实例,这些函数指针最终被初始化到std::array中,运行时通过索引调用对应函数就能得到目标类型的variant。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 07:52:37