C ++ 11 and later versions define free functions begin , end , empty , etc. in the std namespace. For most containers, these functions call the corresponding member function. But for some containers (e.g. valarray ), these free functions are overloaded (initializer_list does not have a begin () element). Therefore, to iterate over any containers, you should use free functions and to search for functions for a container from namespaces other than std ADL, you should use:
template<typename C> void foo(C c) { using std::begin; using std::end; using std::empty; if (empty(c)) throw empty_container(); for (auto i = begin(c); i != end(c); ++i) { } }
Question 1 : Am I right? Are begin and end expected via ADL?
But ADL rules specify that if the argument type is a specialized class structure, ADL includes the namespaces of all the template arguments. And then the Boost.Range library enters the game, it defines boost::begin , boost::end , etc. These functions are defined as follows:
template< class T > inline BOOST_DEDUCED_TYPENAME range_iterator<T>::type begin( T& r ) { return range_begin( r ); }
If I use std::vector<boost::any> and Boost.Range, I run into problems. std :: begin and boost :: begin overloads are ambiguous. What is it, I canβt write the template code that will find the free begin via ADL. If I use std::begin explicitly, I expect any std:: container to have a begin member.
Question 2 : What should I do in this case?
Rely on having a member function? The easiest way.
Ban Boost.Range? Well, algorithms that take a container instead of a pair of iterators are convenient. Boost.Range adapters (containers that lazily apply the algorithm to the container) are also convenient. But if I do not use Boost.Range in my code, it can still be used in the boost library (except Range). This makes the template code very fragile.
Ban Boost?