C++11 et les versions ultérieures définissent des fonctions libres begin
, end
, empty
etc. dans l'espace de noms std. Pour la plupart des conteneurs, ces fonctions invoquent la fonction membre correspondante. Mais pour certains conteneurs (comme valarray
) ces fonctions libres sont surchargées (initializer_list n'a pas de membre begin()). Ainsi, pour itérer sur un conteneur, il faut utiliser des fonctions libres et pour trouver des fonctions pour le conteneur à partir d'espaces de noms autres que std
ADL devrait être utilisé :
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 : Ai-je raison ? Est-ce que begin
y end
que l'on peut trouver via ADL ?
Mais les règles ADL spécifient que si le type d'un argument est une spécialisation de modèle de classe, ADL inclut les espaces de noms de tous les arguments de modèle. Et puis la bibliothèque Boost.Range entre en jeu, elle définit boost::begin
, boost::end
etc. Ces fonctions sont définies comme suit :
template< class T >
inline BOOST_DEDUCED_TYPENAME range_iterator<T>::type begin( T& r )
{
return range_begin( r );
}
Si j'utilise std::vector<boost::any>
et un Boost.Range je rencontre des problèmes. Les surcharges std::begin et boost::begin sont ambiguës. Cela veut dire que je ne peux pas écrire de code template qui trouvera un begin
via ADL. Si j'utilise explicitement std::begin
Je m'attends à ce que toute personne non std::
a un membre begin
.
Question 2 : Que dois-je faire dans ce cas ?
S'appuyer sur la présence de la fonction de membre ? Le moyen le plus simple.
Ban Boost.Range ? Eh bien, les algorithmes qui prennent un conteneur au lieu d'une paire d'itérateurs sont convaincants. Les adaptateurs Boost.Range (conteneurs qui appliquent paresseusement un algorithme à un conteneur) sont également pratiques. Mais si je n'utilise pas Boost.Range dans mon code, il peut toujours être utilisé dans une bibliothèque boost (autre que Range). Cela rend le code template vraiment fragile.
Ban Boost ?