c++ - 为什么 std::get 只有两个 range::subrange 函数重载?
问题描述
标准中有四种 pair-like 类型,即std::array
、std::pair
、std::tuple
和ranges::subrange
,其中std::get
for的重载ranges::subrange
在[range.subrange#access-10]中定义:
template<size_t N, class I, class S, subrange_kind K> requires (N < 2) constexpr auto get(const subrange<I, S, K>& r); template<size_t N, class I, class S, subrange_kind K> requires (N < 2) constexpr auto get(subrange<I, S, K>&& r);
效果:相当于:
if constexpr (N == 0) return r.begin(); else return r.end();
并且ranges::subrange::begin()
有两个重载:
constexpr I begin() const requires copyable<I>;
[[nodiscard]] constexpr I begin() requires (!copyable<I>);
我注意到这std::get
只有两个重载,并且非常量左值引用没有相应的重载,这使得我们无法使用非迭代器(godbolt)std::get
应用于左值:input_range
copyable
#include <ranges>
#include <sstream>
int main() {
auto ints = std::istringstream{"42"};
auto is = std::ranges::istream_view<int>(ints);
std::ranges::input_range auto r = std::ranges::subrange(is);
auto b = r.begin(); // OK
auto b2 = std::get<0>(r); // Error, passing 'const subrange' as 'this' argument discards qualifiers
}
那么为什么std::get
只有两个函数重载ranges::subrange
呢?它会错过ranges::subrange&
and的重载const ranges::subrange&&
吗?这是标准缺陷还是故意的?
解决方案
作为一般规则,subrange
格式良好且定义明确的代码表示一个有效范围,如果它存储一个大小,则该大小等于该范围的大小。这反映在每个非默认构造函数的前提条件中(默认构造状态仍然可以部分形成)。begin
由于引入了仅移动迭代器(因为非常量需要将迭代器移出),这有点混乱,但仍然是设计意图。
换句话说,与、或subrange
完全不同。这三个是没有语义的值的聚合,它们的重载通过透明地传播 cv 限定和值类别来反映这一点。另一方面,它确实有语义——它不仅仅是一对迭代器和哨兵。它只用于阅读,从不用于写作。这就是为什么按价值返回的原因。pair
tuple
array
get
subrange
get
get
subrange
get
提供非常量左值重载没有多大意义;通过可变引用返回是不可能的;通过引用返回 const 不同于其他一切(也令人惊讶)。按值返回意味着在唯一的情况下它会有所不同,get
在左值subrange
上是一种破坏性操作,这将是非常出乎意料的。
推荐阅读
- reactjs - 在反应生命周期挂钩中用 setTimeout 替换 setInterval
- c# - 在 C# 中使用带有空格的 Directory.Move,当 Filepath 从多个 List 条目创建时,这些条目由 DirectoryInfo 生成
- javascript - 如何在热敏打印机中打印页面
- c# - VSCode - linter 找不到 Blazor SyncFusion 组件
- ios - Swift SKNode 位置帮助 - 移动时精灵位置始终为 0,0
- html - 第 1 页后无法从 jquery DataTable 表行中获取属性值
- contentful - 在从旧数据库迁移到 Contentful 时添加 sys 日期属性
- javascript - class sendAPICallback extends dAPIMessage { ^ TypeError: Class extends value undefined is not a constructor or null
- javascript - 有没有办法从通过 JavaScript 嵌入的 YouTube 视频中获取章节?
- html - 为什么在这种情况下隐藏的溢出不能像预期的那样工作?