C++ 基于范围的语句定义冗余

C++ 基于范围的语句定义冗余,c++,for-loop,range,c++11,argument-dependent-lookup,C++,For Loop,Range,C++11,Argument Dependent Lookup,查看n3092,在§6.5.4中,我们发现了基于范围的for循环的等效性。然后它继续说明\u开始和\u结束等于什么。它区别于阵列和其他类型,我发现这是多余的(也就是令人困惑的) 它说,对于数组类型,\u开始和\u结束是您所期望的:指向第一个的指针和指向结束后的指针。然后对于其他类型,\uuu begin和\uu end与begin(\uu范围)和end(\uu范围),使用ADL。名称空间std关联,以查找,§24.6.5中定义的std::begin和std::end 但是,如果我们看一下std:

查看n3092,在§6.5.4中,我们发现了基于范围的for循环的等效性。然后它继续说明
\u开始
\u结束
等于什么。它区别于阵列和其他类型,我发现这是多余的(也就是令人困惑的)

它说,对于数组类型,
\u开始
\u结束
是您所期望的:指向第一个的指针和指向结束后的指针。然后对于其他类型,
\uuu begin
\uu end
begin(\uu范围)
end(\uu范围)
,使用ADL。名称空间
std
关联,以查找
,§24.6.5中定义的
std::begin
std::end

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

当为其他类型给出的定义同样适用时,为什么需要将数组与其他类型区分开来,查找
std::begin
std::end


为方便起见,一些简短的引用:

§6.5.4基于范围的声明 -如果RangeT是数组类型,则begin expr和end expr分别是_range和_range+_绑定,其中_绑定是数组绑定。如果_range是大小未知的数组或类型不完整的数组,则程序的格式不正确

-否则,begin expr和end expr分别是begin(_范围)和end(_范围),其中begin和end通过参数相关的查找(3.4.2)进行查找。出于此名称查找的目的,名称空间std是一个关联的名称空间

§24.6.5范围访问
模板T*begin(T(&array)[N]);
返回:数组

template <class T, size_t N> T* end(T (&array)[N]);
模板T*end(T(&array)[N]);
返回:数组+N


这避免了ADL出现转角情况:

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

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

因为ADL在调用
begin(a)
时会找到other::begin,所以等价的代码会中断,导致一个令人困惑的编译错误(就像
end(a)
会返回一个t*)一样,“不能将int与other::t*进行比较”,或者不同的行为(如果定义了other::end并且做了类似的意外操作).

Nice:)它还允许用户使用循环,而无需首先包含任何标题。@Johannes:应该没有问题;根据FCD中的24.6.5,如果您包括一个容器标题,那么您也会得到开始和结束。不在stdlib中的类型应该使任何自定义的开始/结束都类似地可用,因此只有在极少数情况下才需要它。(但是,该死,如果你碰到它,那是一个很大的麻烦。)@Roger迭代
int[]
就是这样一种情况,我的意思是需要一个标题。一行摘要:通过ADL查找
begin
end
可能找不到
std::begin
std::end
namespace other {
  struct T {};
  int begin(T*) { return 42; }
}

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