基于范围的 for 语句定义冗余

发布于 2024-08-29 13:02:32 字数 1367 浏览 4 评论 0原文

查看 n3092,在第 6.5.4 节中,我们找到了基于范围的 for 循环的等效项。然后它继续说明 __begin__end 等于什么。它区分数组和其他类型,我发现这是多余的(又名令人困惑)。

它表示对于数组类型,__begin__end 就是您所期望的:指向第一个的指针和指向末尾的指针。那么对于其他类型,__begin__end等于begin(__range)end(__range),其中日常生活活动能力。关联命名空间 std,以便找到 < 中定义的 std::beginstd::end /代码>,§24.6.5。

但是,如果我们查看 std::beginstd::end 的定义,它们都是为数组和容器类型定义的。数组版本的作用与上面完全相同:指向第一个的指针,指向末尾的指针。

为什么需要将数组与其他类型区分开来,因为其他类型的定义也同样有效,可以找到 std::beginstd::end


为方便起见,摘录了一些引文:

§6.5.4 基于范围的 for 语句

—如果 _RangeT 是数组类型,则 begin-expr 和 end-expr 分别是 __range 和 __range + __bound,其中 __bound 是数组边界。如果 _RangeT 是未知大小的数组或不完整类型的数组,则程序格式错误。

— 否则,begin-expr 和 end-expr 分别是 begin(__range) 和 end(__range),其中 begin 和 end 是通过参数相关查找来查找的 (3.4.2)。出于此名称查找的目的,命名空间 std 是关联的命名空间。

§24.6.5 范围访问

模板 T* 开始(T (&数组)[N]);

返回:数组。

模板 T* end(T (&数组)[N]);

返回:数组+N。

Looking at n3092, in §6.5.4 we find the equivalency for a range-based for loop. It then goes on to say what __begin and __end are equal to. It differentiates between arrays and other types, and I find this redundant (aka confusing).

It says for arrays types that __begin and __end are what you expect: a pointer to the first and a pointer to one-past the end. Then for other types, __begin and __end are equal to begin(__range) and end(__range), with ADL. Namespace std is associated, in order to find the std::begin and std::end defined in <iterator>, §24.6.5.

However, if we look at the definition of std::begin and std::end, they are both defined for arrays as well as container types. And the array versions do exactly the same as above: pointer to the first, pointer to one-past the end.

Why is there a need to differentiate arrays from other types, when the definition given for other types would work just as well, finding std::begin and std::end?


Some abridged quotes for convenience:

§6.5.4 The range-based for statement

— if _RangeT is an array type, begin-expr and end-expr are __range and __range + __bound, respectively, where __bound is the array bound. If _RangeT is an array of unknown size or an array of incomplete type, the program is ill-formed.

— otherwise, begin-expr and end-expr are begin(__range) and end(__range), respectively, where begin and end are looked up with argument-dependent lookup (3.4.2). For the purposes of this name lookup, namespace std is an associated namespace.

§24.6.5 range access

template <class T, size_t N> T* begin(T (&array)[N]);

Returns: array.

template <class T, size_t N> T* end(T (&array)[N]);

Returns: array + N.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

逆光下的微笑 2024-09-05 13:02:32

这避免了 ADL 的极端情况:

namespace other {
  struct T {};
  int begin(T*) { return 42; }
}

other::T a[3];
for (auto v : a) {}

因为 ADL 在调用 begin(a) 时找到了 other::begin,所以等效的代码会中断,导致令人困惑的编译错误(类似于“can't Compare”) int to other::T*”,因为 end(a) 将返回 T*)或不同的行为(如果定义了 other::end 并做了同样意想不到的事情)。

This avoids a corner-case with ADL:

namespace other {
  struct T {};
  int begin(T*) { return 42; }
}

other::T a[3];
for (auto v : a) {}

Because ADL finds other::begin when calling begin(a), the equivalent code would break causing a confusing compile error (along the lines of "can't compare int to other::T*" as end(a) would return a T*) or different behavior (if other::end was defined and did something likewise unexpected).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文