张裕 发表于 2025-5-20 08:45:25

std::ranges::views::as_const 和 std::ranges::as_const_view

std::ranges::views::as_const 和 std::ranges::as_const_view 是 C++23 引入的视图适配器,用于天生一个不可变的视图,确保通过该视图访问元素时,元素被视为常量。以下是详细说明和示例:
根本概念



[*] 功能:

[*] 将输入范围的元素逼迫视为 const,防止意外修改。
[*] 天生一个惰性视图,不复制数据,仅在访问时应用常量性。

[*] 输入要求:

[*] 输入范围可以是任何范例的范围(如 vector、list 或自定义范围)。
[*] 不修改原始数据,仅修改访问权限。

函数原型

在标头 <ranges> 定义
template< ranges::view V >     requires ranges::input_range<V>
class as_const_view
    : public ranges::view_interface<as_const_view<V>>(1)(C++23 起)namespace views {     inline constexpr /* 未指明 */ as_const = /* 未指明 */;
}(2)(C++23 起) 调用签名
template< ranges::viewable_range R >     requires /* 见下文 */
constexpr ranges::view auto as_const( R&& r );(C++23 起)
参数与返回值



[*] 参数:

[*] 输入范围 r(需满足 viewable_range)。

[*] 返回值:as_const_view 对象,表现只读视图。
[*] 活动:

[*] 若输入范围的元素范例已为 const,视图活动不变。
[*] 若元素可修改,通过视图访问时变为 const。

数据成员

成员说明V base_ (私有)底层视图
(仅用于阐述的成员对象*) 成员函数

(构造函数)
构造一个 as_const_view
(公开成员函数) base
返回底层视图 V
(公开成员函数) begin
返回 as_const_view 的首迭代器
(公开成员函数) end
返回 as_const_view 的尾迭代器
(公开成员函数) size
如果其有界则返回视图的大小
(公开成员函数) reserve_hint
(C++26)
返回底层 approximately_sized_range 的估计大小
(公开成员函数) 继承自 std::ranges::view_interface

empty
返回视图是否为空,仅当视图满足 forward_range 时提供
(std::ranges::view_interface<D> 的公开成员函数) cbegin
(C++23)
返回指向范围起始的常量迭代器
(std::ranges::view_interface<D> 的公开成员函数) cend
(C++23)
返回对应于范围常量迭代器的哨位
(std::ranges::view_interface<D> 的公开成员函数) operator bool
返回派生视图是否为非空,仅当 ranges::empty 可应用于它时提供
(std::ranges::view_interface<D> 的公开成员函数) data
返回派生视图的数据的地址,仅当视图的迭代器范例满足 contiguous_iterator 时提供
(std::ranges::view_interface<D> 的公开成员函数) front
返回派生视图中的首元素,仅当视图满足 forward_range 时提供
(std::ranges::view_interface<D> 的公开成员函数) back
返回派生视图中的末元素,仅当视图满足 bidirectional_range 与 common_range 时提供
(std::ranges::view_interface<D> 的公开成员函数) operator[]
返回派生视图中的第 n 个元素,仅当视图满足 random_access_range 时提供
(std::ranges::view_interface<D> 的公开成员函数) 示例代码

基础用法:禁止修改元素

#include <ranges>
#include <vector>
#include <iostream>

int main()
{
    std::vector<int> vec = {1, 2, 3, 4, 5};
    auto const_view = vec | std::views::as_const;

    for (const auto& elem : const_view)
    {
      // elem 类型为 const int&,以下代码将编译失败
      // elem = 10; // Error: 无法修改常量引用
      std::cout << elem << " ";
    }
    // 输出:1 2 3 4 5
} 联合算法确保只读操作

#include <ranges>
#include <vector>
#include <iostream>
#include <algorithm>

void process_data(std::ranges::input_range auto&& r)
{
    // 确保 r 的元素为只读
    for (const auto& elem : r | std::views::as_const)
    {
      // elem 不可修改
      std::cout << elem << " ";
    }
}

int main()
{
    std::vector<int> data = {10, 20, 30};
    process_data(data); // 安全传递只读视图
} 处理嵌套数据结构

#include <ranges>
#include <vector>
#include <list>

int main()
{
    std::vector<std::list<int>> nested =
    {
      {1, 2}, {3, 4}, {5, 6}
    };

    auto const_nested = nested | std::views::as_const;

    for (const auto& inner_list : const_nested)
    {
      // inner_list 是 const std::list<int>&
      for (const auto& num : inner_list)
      {
            // num 是 const int&
            std::cout << num << " ";
      }
    }
    // 输出:1 2 3 4 5 6
} 高级用法

链式视图操作

#include <ranges>
#include <vector>
#include <algorithm>
#include <iostream>

int main()
{
    std::vector<int> vec = {5, 3, 4, 1, 2};
    auto view = vec
      | std::views::filter([](int x) { return x % 2 == 0; }) // 筛选偶数
      | std::views::as_const; // 结果转为只读

    // 尝试修改会编译失败
    // *view.begin() = 10; // Error: 无法修改常量引用

    for (int x : view)
    {
      std::cout << x << " "; // 输出:4 2
    }
} 处理代理引用(如 vector<bool>)

#include <ranges>
#include <vector>
#include <iostream>

int main()
{
    std::vector<bool> flags = {true, false, true};
    auto const_flags = flags | std::views::as_const;

    for (const auto& flag : const_flags)
    {
      // flag 类型为 const bool&(代理引用)
      std::cout << std::boolalpha << flag << " ";
    }
    // 输出:true false true
} 注意事项


[*] 常量性传递:

[*] 若原始元素已为 const,视图不会改变其活动。
[*] 对非 const 元素,视图逼迫其视为 const。

[*] 性能与开销:

[*] 惰性求值,无额外内存开销。
[*] 仅修改范例系统,运行时无性能损失。

[*] 适用场景:

[*] 传递范围给函数时逼迫只读。
[*] 在多线程或需要数据不变性时增强安全性。

[*] 与 const_cast 的区别:

[*] as_const_view 通过范例系统安全地添加常量性,而非逼迫转换。

总结



[*] std::ranges::views::as_const 提供了一种范例安全的方式,确保通过视图访问的元素不可修改。
[*] 适用于需要逼迫数据只读性的场景,增强代码安全性和可维护性。
[*] 与标准算法和其他视图适配器无缝联合,支持复杂的链式操作。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: std::ranges::views::as_const 和 std::ranges::as_const_view