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

如何用std::ranges::to将范围转换为std::array?

问题:如何像std::ranges::to<std::vector>那样优雅转换编译期已知大小的视图到std::array?

我想把以下用std::ranges::to转换为std::vector的代码,改成转换为std::array,但发现std::ranges::to不支持直接转std::array:

constexpr auto dice = std::views::iota(1, 7);
static_assert(dice.size() == 6);
std::print("{}
", dice | std::ranges::to<std::vector>());

我知道可以显式构造std::array,但这种方式重复且不够优雅,不符合和std::vector用法对称的需求:

constexpr auto arr = [&]() {
    std::array<std::ranges::range_value_t<decltype(dice)>, dice.size()> result;
    std::ranges::copy(dice, result.begin());
    return result;
}();
std::print("{}
", arr);

我尝试过自定义辅助函子,但因无法传递constexpr参数失效;还实现了一个模板函数,但不够优雅:

template<auto& rng>
consteval auto to_arr() -> std::array<std::ranges::range_value_t<decltype(rng)>, std::ranges::size(rng)> {
    std::array<std::ranges::range_value_t<decltype(rng)>, rng.size()> result;
    std::ranges::copy(rng, result.begin());
    return result;
}

请问是否存在更简洁、与std::vector用法对称的转换方式?(此问题针对所有编译期已知大小的视图,如transform后的视图)


回答

C++20/23标准中的std::ranges::to确实不支持直接推导std::array的大小——因为std::array的尺寸是模板参数,而ranges::to的原生设计针对的是可动态分配的容器。不过有几种方案能实现接近你需求的优雅转换:

1. 扩展std::ranges::to适配std::array

通过给标准命名空间添加std::array的to特化,实现和vector完全一致的语法:

namespace std::ranges {
    template<std::ranges::range R>
        requires std::ranges::sized_range<R> && std::is_constant_evaluated()
    constexpr auto to<std::array>(R&& r) {
        using ValueType = std::ranges::range_value_t<R>;
        constexpr size_t Size = std::ranges::size(r);
        std::array<ValueType, Size> arr;
        std::ranges::copy(std::forward<R>(r), arr.begin());
        return arr;
    }
}

使用时和原vector写法完全对称:

std::print("{}
", dice | std::ranges::to<std::array>());

注意:扩展标准命名空间在实际项目中可行,但需确认编译器兼容性。

2. 自定义管道适配器to_array

实现一个独立的管道操作符,语法和ranges::to<vector>完全对齐,且无需修改标准库:

struct to_array_t {
    template<std::ranges::input_range R>
        requires std::ranges::sized_range<R> && std::is_constant_evaluated()
    constexpr auto operator()(R&& r) const {
        using ValueType = std::ranges::range_value_t<R>;
        constexpr size_t Size = std::ranges::size(r);
        std::array<ValueType, Size> arr;
        std::ranges::copy(std::forward<R>(r), arr.begin());
        return arr;
    }
};

inline constexpr to_array_t to_array;

使用示例:

std::print("{}
", dice | to_array);

这个方案支持所有编译期尺寸已知的视图,语法简洁且符合你的对称需求。

3. 等待C++26原生支持

目前C标准委员会正在讨论让std::ranges::to原生支持std::array的推导,C26标准中大概率会加入此功能,届时可以直接使用std::ranges::to<std::array>而无需额外代码。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 15:33:20