std::ranges::views::values要求value_type有second成员,适用于std::map等关联容器及pair元素的vector,需C++20、<ranges>头文件和现代标准库支持,返回懒求值视图,解引用得原值引用,不可绑定临时对象。

std::ranges::views::values 要求容器有 value_type::second 成员
直接对 std::map 或 std::unordered_map 使用 std::ranges::views::values 是合法的,但前提是容器的 value_type(即 std::pair<const k v></const>)能通过 .second 提取值。标准库中,std::ranges::views::values 的实现正是依赖这一访问模式 —— 它对每个元素调用 std::forward<r>(r).second</r>。
这意味着:std::map<int std::string></int> 可以用;但如果你自己写了个结构体作为 value_type 且没有 second 成员,就会编译失败,错误类似:no member named 'second' in 'MyType'。
-
std::map、std::unordered_map、std::multimap等标准关联容器都满足条件 -
std::vector<:pair double>></:pair>同样可用 —— 注意不是std::vector本身,而是其元素为pair的情况 - 不能用于
std::vector<foo></foo>(除非Foo有second成员)
必须启用 C++20 且包含对应头文件
std::ranges::views::values 是 C++20 引入的,不支持 C++17 或更早版本。编译时需显式开启 C++20(如 g++ -std=c++20),并包含 <ranges> 头文件 —— 仅靠 <map> 或 <vector> 不够。
- 遗漏
#include <ranges>会导致编译错误:'views' is not a member of 'std::ranges' - Clang/GCC 需确认标准库支持:libstdc++ 12+ 或 libc++ 14+ 才完整实现该视图
- MSVC 2019 v16.11+ 开始支持,但早期版本可能触发 internal compiler error,建议用 VS2022 17.4+
返回的是视图,不是新容器;迭代器类型与原容器一致
std::ranges::views::values 返回的是一个懒求值的视图对象,底层不拷贝数据,也不改变原容器生命周期。它的迭代器类型继承自原容器的迭代器 —— 比如对 std::map 使用,得到的是 std::map<K,V>::iterator 衍生的 view 迭代器,解引用后是 V&(非常量引用)或 const V&(取决于原容器是否 const)。
立即学习“C++免费学习笔记(深入)”;
- 不能对临时 map 调用:
auto v = std::ranges::views::values(std::map{...})→v持有悬空引用 - 修改视图元素会同步反映到原 map:
*it = "new"(it来自 values view)等价于修改map_iter->second - 不能用
std::vector构造函数直接初始化:std::vector(v)会失败,因为v不是Range<T>(缺少begin()/end()的 ADL 查找兼容性),应改用std::vector(v.begin(), v.end())或 C++23 的std::ranges::to<std::vector>
替代方案:当 views::values 不可用或不适用时
若编译环境受限(如仅 C++17),或容器类型不满足 second 访问要求,可手写等效逻辑。最常见的是用 std::ranges::transform_view 显式投影:
auto values_view = std::ranges::views::transform(my_map, [](const auto& p) -> const auto& { return p.second; });
注意返回类型要匹配:对非 const map,若想获得可修改的引用,去掉 const 限定;若 map 是 const,则必须用 const auto&,否则编译失败。
- 这种写法兼容 C++17(只要
std::ranges::views::transform可用,实际仍需 C++20) - 真正降级到 C++17 应改用传统 for 循环或
std::transform+std::back_inserter - 若 map 元素是 move-only 类型(如
std::unique_ptr),views::values仍可安全使用,但transform_view中的 lambda 必须避免复制 —— 用std::move(p.second)并确保返回类型为auto&&


















