Like many people these days I have been trying the different features that C++11 brings. One of my favorites is the \"range-based for loops\".
I understand that:
I would like to elaborate some parts of @Steve Jessop's answer, for which at first I didn't understand. Hope it helps.
std::begin
calls thebegin()
member function anyway, so if you only implement one of the above, then the results should be the same no matter which one you choose. That's the same results for ranged-based for loops, and also the same result for mere mortal code that doesn't have its own magical name resolution rules so just doesusing std::begin;
followed by an unqualified call tobegin(a)
.If you implement the member functions and the ADL functions, though, then range-based for loops should call the member functions, whereas mere mortals will call the ADL functions. Best make sure they do the same thing in that case!
https://en.cppreference.com/w/cpp/language/range-for :
- If ...
- If
range_expression
is an expression of a class typeC
that has both a member namedbegin
and a member namedend
(regardless of the type or accessibility of such member), thenbegin_expr
is__range.begin(
) andend_expr
is__range.end()
;- Otherwise,
begin_expr
isbegin(__range)
andend_expr
isend(__range)
, which are found via argument-dependent lookup (non-ADL lookup is not performed).
For range-based for loop, member functions are selected first.
But for
using std::begin;
begin(instance);
ADL functions are selected first.
Example:
#include
#include
using std::cout;
using std::endl;
namespace Foo{
struct A{
//member function version
int* begin(){
cout << "111";
int* p = new int(3); //leak I know, for simplicity
return p;
}
int *end(){
cout << "111";
int* p = new int(4);
return p;
}
};
//ADL version
int* begin(A a){
cout << "222";
int* p = new int(5);
return p;
}
int* end(A a){
cout << "222";
int* p = new int(6);
return p;
}
}
int main(int argc, char *args[]){
// Uncomment only one of two code sections below for each trial
// Foo::A a;
// using std::begin;
// begin(a); //ADL version are selected. If comment out ADL version, then member functions are called.
// Foo::A a;
// for(auto s: a){ //member functions are selected. If comment out member functions, then ADL are called.
// }
}