在C++23 GCC13.2.0中如何结合std::lcm与std::ranges::fold_left?求更佳方案
std::lcm与std::ranges::fold_left结合使用的问题解答
尝试将C++23中的
std::lcm与std::ranges::fold_left结合使用时,在GCC 13.2.0及cppinsights.io环境下编译失败。对比std::plus、std::multiplies与std::lcm的函数签名后定位了问题根源,现针对以下三个问题给出解答:
1. 推荐的标准实现方式是什么?
最直接的标准方案是用lambda表达式包装std::lcm,适配fold_left的调用要求,代码示例:
#include <numeric> #include <ranges> #include <vector> int main() { std::vector<int> nums{4, 6, 8}; auto result = std::ranges::fold_left(nums, 1, [](auto a, auto b) { return std::lcm(a, b); }); }
这种写法完全符合C++23标准,既能避开签名不兼容问题,又保持了代码的简洁性和可读性。
2. 是否必须自行实现结构体?
不需要。除了lambda方案,你也可以用std::bind_front或者std::bind做适配,但lambda的可读性和易用性更优。如果确实需要复用这个适配逻辑,自定义仿函数结构体是可选方案,但绝非必须——lambda已经能覆盖绝大多数场景的需求。
3. 为何这些接口设计不一致?
核心原因是std::lcm(以及std::gcd)的设计定位和std::plus、std::multiplies这类算术仿函数完全不同:
std::plus、std::multiplies是可调用对象模板,本身是仿函数类型,实例化后可以直接作为二元函数对象传递给算法,它们的operator()签名是(const T&, const T&),完美匹配fold_left这类算法对二元操作的要求。- 而
std::lcm是普通函数模板,它的签名是template<typename M, typename N> constexpr std::common_type_t<M,N> lcm(M m, N n);。直接传递std::lcm时,编译器无法推导模板参数(因为fold_left需要的是一个可调用对象,而非模板本身)。另外,std::lcm有额外的前置条件(输入必须是非负整数),这也是和普通算术操作设计考量不同的地方。
内容的提问来源于stack exchange,提问作者Torsten Knodt
相关产品推荐
相关产品推荐

