Should the `begin` and `end` functions be overloaded inside the namespace `std`?

Viewed 97

Recently I have been working on a code base which uses MFC and objects such as CArray<T, U>.

Some parts of new code which has been written make use of the STL and <algorithm> library.

For example

CArray<int int> carray;
carray // do stuff
std::vector<int> stlvector(begin(carray), end(carray));
stlvector.dostuff() // do stuff

I recently asked a question about creating iterators for a class such as CArray, which I do not have access to.

I now have some further questions about this. Here is my first question:

  • Should the begin and end functions be inside the std namespace?

I will ask the other questions separately and provide links to them shortly, replacing this line of text when those links are available.

2 Answers

It can be useful to look at a non-trivial use of begin:

CArray<int> carray;
for (auto c : carray){
}

The begin is hidden in the range-for loop! Which begin(carray) is this? The name lookup rules here say that only argument-dependent lookup is done. There's no attempt to look at std::begin, since std is not at all related to CArray.

This makes sense. CArrayIterator begin(CArray) is a function that belongs to CArray, and therefore should be in the same namespace.

To properly define the function, it should be defined in the same namespace as CArray. To properly use it generically, it should be used like, similar to the two-step swap idiom:

{
    using std::begin;
    begin(my_carray);
}

Alternative you might consider using some C++20 features that can wrap CArray, such as std::span and std::ranges::view_interface

Related