The following code example is taken from the book
C++20 - The Complete Guide
by Nicolai M. Josuttis,
Leanpub, 2021
The code is licensed under a
Creative Commons Attribution 4.0 International License.
// raw code
#include <iostream>
#include <cstdlib>
#include <filesystem>
// type with member begin():
struct MemberBegin {
//...
int* begin() const {
std::cout << "MemberBegin::begin()\n";
return new int{42};
}
};
// type with global free-standing begin():
struct GlobalBegin {
//...
};
int* begin(GlobalBegin) {
std::cout << "::begin(GlobalBegin)\n";
return new int{42};
}
// type with free-standing begin() in a namespace:
namespace ns {
struct NsBegin {
//...
};
int* begin(NsBegin) {
std::cout << "ns::begin(NsBegin)\n";
return new int{42};
}
}
int main()
{
MemberBegin m;
GlobalBegin g;
ns::NsBegin n;
std::filesystem::directory_iterator dir{"."};
// direct std::begin() doesn't always work:
std::cout << "--- std::begin() direct:\n";
{
std::begin(m); // OK: MemberBegin::begin()
//std::begin(g); // ERROR: begin(GlobalBegin) not found
//std::begin(n); // ERROR: nd::begin(ns::NsBegin) not found
std::begin(s); // OK: std::begin(NsStdBegin)
//std::begin(dir); // ERROR: doesn't work for filesystem iterators
}
// std::begin() with using declaration:
std::cout << "--- using std::begin():\n";
{
using std::begin;
begin(m); // OK: ::begin(m)
begin(g); // OK: ::begin(g)
begin(n); // OK: ns::begin(NsBegin)
begin(dir); // OK
}
// std::ranges::begin() works better:
std::cout << "--- std::ranges::begin() direct:\n";
{
std::ranges::begin(m); // OK: ::begin(m)
std::ranges::begin(g); // OK: ::begin(g)
std::ranges::begin(n); // OK: ns::begin(NsBegin)
std::ranges::begin(dir); // OK
}
// for std::ranges::begin() a using declaration doesn't change anything:
std::cout << "--- using std::ranges::begin():\n";
{
using std::ranges::begin;
begin(m); // OK: ::begin(m)
begin(g); // OK: ::begin(g)
begin(n); // OK: ns::begin(NsBegin)
begin(dir); // OK
}
}