[英]Shouldn't the begin() and end() functions be member functions of the template class Vector?
In page 82 of the draft of Chapter 3 : A Tour of C++: Abstraction Mechanisms the author writes: 在第3章:C ++之旅:抽象机制的草案的第82页中 ,作者写道:
If we also want to use the range-for loop for our Vector , we must define suitable begin() and end() functions: 如果我们还想对Vector使用range-for循环,则必须定义合适的begin()和end()函数:
template<typename T>
T∗ begin(Vector<T>& x)
{
return &x[0]; // pointer to first element
}
template<typename T>
T∗ end(Vector<T>& x)
{
return x.begin()+x.size(); // pointer to one-past-last element
}
Given those, we can write: 有了这些,我们可以写:
void f2(const Vector<string>& vs) // Vector of some strings
{
for (auto s : vs)
cout << s << ’\n’;
}
Notice that the class template Vector is defined in page 81 of the draft. 请注意,类模板Vector在草稿的第81页中定义。
For range-based for to work, the compiler needs to find a suitable function to get the iterators. 为了使基于范围的工作正常,编译器需要找到合适的函数来获取迭代器。
If the type used is a class, it'll first look for member functions begin
and end
in the scope of that class. 如果使用的类型是类,则它将首先查找成员函数,该函数在该类的范围内begin
和end
。
If the type is not a class or the are no such member functions, it looks them up by Argument Dependent Lookup. 如果类型不是类或没有此类成员函数,则通过“ 参数依赖查找”查找它们。
This is the reason range-based for works on C-arrays. 这就是基于范围进行C阵列工作的原因。 Obviously, arrays can't have member functions, so standard library provides two functions defined similarly to this: 显然,数组不能具有成员函数,因此标准库提供了两个与此定义类似的函数:
template<typename T, size_t N>
T* begin( T(&array)[N] )
{
return array;
}
and similarly for end
. 同样地end
。
To answer your question from the title: they can be, but it's not a neccesity. 从标题回答您的问题: 可以 ,但不是必须的。 You can define free functions in the same namespace as your class and they'll be found. 您可以在与类相同的名称空间中定义自由函数,然后就会找到它们。
If it is not an array or a container with .begin()
and .end()
it will look up by Argument dependent name . 如果它不是具有.begin()
和.end()
的数组或容器,则将通过依赖于参数的name查找。
Keep in mind these facts about range-based for: 请记住以下有关基于范围的事实:
Automatically recognizes arrays. 自动识别数组。
Recognizes containers that have .begin() and .end(). 识别具有.begin()和.end()的容器。
Uses argument-dependent lookup begin() and end() for anything else. 使用依赖于参数的查找begin()和end()进行其他操作。
In such a range based for: 在这样的范围内基于:
for ( for-range-declaration : expression ) statement
the standard says that the compiler looks for either members ( (expression).begin()
, (expression).end()
) or free functions ( begin((expression))
, end((expression))
) if expression is of class type. 标准说,如果expression是类,则编译器将查找成员( (expression).begin()
, (expression).end()
)或自由函数( begin((expression))
, end((expression))
)。类型。
Therefore you can either provide member functions OR free functions (which need to be in scope for argument dependant lookup). 因此, 您既可以提供成员函数,也可以提供自由函数 (这些函数必须在依赖于参数的查找范围内)。
C++11, § 6.5.4 [stmt.ranged] C ++ 11,第6.5.4节[stmt.ranged]
This is what a ranged-based for does according to the standard: 这是基于标准的基于范围的操作:
for ( for-range-declaration : expression ) statement
range-init = ( expression )
{
auto && __range = range-init;
for ( auto __begin = begin-expr,
__end = end-expr;
__begin != __end;
++__begin )
{
for-range-declaration = *__begin;
statement
}
}
The begin-expr
and end-expr
are described as: begin-expr
和end-expr
描述为:
if
_RangeT
is an array type, begin-expr and end-expr are _ range and 如果_RangeT
是数组类型,则begin-expr和end-expr是_ range 和 _range + _ bound , respectively, where _range + _ bound ,其中 _bound is the array bound. _bound是数组绑定。 If _RangeT is an array of unknown size or an array of incomplete type, the program is ill-formed; 如果_RangeT是未知大小的数组或类型不完整的数组,则程序格式错误 ;if
_RangeT
is a class type, the unqualified-ids begin and end are looked up in the scope of class _RangeT as if by class member access lookup (3.4.5), and if either (or both) finds at least one declaration, beginexpr and end-expr are __range.begin() and __range.end(), respectively; 如果_RangeT
是类类型,则在_RangeT类的范围内查找不合格ID的begin和end,就像通过类成员访问查找(3.4.5)一样,并且如果一个(或两个)都找到至少一个声明,则beginexpr和end-expr分别是__range.begin()和__range.end();otherwise, begin-expr and end-expr are
begin(__range)
andend(__range)
, respectively, wherebegin
andend
are looked up with argument-dependent lookup (3.4.2). 否则, begin-expr和end-expr分别是begin(__range)
和end(__range)
,其中begin
和end
是通过与参数相关的查找(3.4.2)查找的。 For the purposes of this name lookup, namespace std is an associated namespace. 出于此名称查找的目的,名称空间std是关联的名称空间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.