ADL and container functions (start, end, etc.)

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) { /* do something */ } } 

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?

+5
source share

Source: https://habr.com/ru/post/1260865/


All Articles