La partie pertinente de la norme est 6.5.4/1:
si _RangeT est un type de classe, le unqualified-id de début et de fin sont
recherché dans le champ d'application de classe _RangeT comme si par un membre de la classe d'accès
recherche (3.4.5), et si l'une (ou les deux) trouve au moins une déclaration,
- expr et de fin expr sont __range.begin()
et __range.end()
,
respectivement;
- dans le cas contraire, commencez-expr et de fin expr sont begin(__range)
et
end(__range)
, respectivement, où de début et de fin sont considérés avec
argument dépendant de recherche (3.4.2). Pour les fins de ce nom
recherche, de l'espace de noms std est associé à un espace de noms.
Ainsi, vous pouvez effectuer l'une des opérations suivantes:
- définir
begin
et end
des fonctions de membre du
- définir
begin
et end
gratuit fonctions qui seront trouvés par ADL (version simplifiée: les mettre dans le même espace de noms que celui de la classe)
- se spécialiser
std::begin
et std::end
std::begin
des appels à l' begin()
fonction de membre de toute façon, donc si vous ne mettez en œuvre l'un des ci-dessus, le résultat devrait être le même, peu importe celle que vous choisissez. C'est les mêmes résultats ont varié à base de boucles, et aussi le même résultat pour le simple mortel code qui ne dispose pas de son propre magique de résolution de nom de règles de juste n' using std::begin;
, suivi par un appel non qualifié pour begin(a)
.
Si vous implémentez les fonctions de membre et de l'ADL fonctions, cependant, puis de la gamme, à base de boucles doivent appeler les fonctions de membre, alors que de simples mortels va appeler l'ADL fonctions. Meilleur assurez-vous qu'ils font la même chose dans ce cas!
Si la chose que vous avez écrit, met en œuvre le conteneur de l'interface, alors il va falloir begin()
et end()
fonctions de membre déjà, ce qui devrait être suffisant. Si c'est une plage qui n'est pas un conteneur (ce qui serait une bonne idée si c'est immuable, ou si vous ne connaissez pas la taille à l'avant), vous êtes libre de choisir.
Les options que vous présentez, notez que vous ne devez pas surcharger std::begin()
. Vous êtes autorisé à se spécialiser modèles standard pour un type défini par l'utilisateur, mais à côté de cela, l'ajout de définitions de l'espace de noms std est un comportement indéfini. Mais de toute façon, spécialisée fonctions standard est un mauvais choix, si seulement en raison de l'absence de fonction partielle de spécialisation signifie que vous ne pouvez le faire pour une seule classe, et pas pour un modèle de classe.