2011-09-28 11 views
8

En una de sus últimas conversaciones, Herb Sutter recomienda preferir las plantillas de funciones gratuitas begin(container)end(container) sobre container.begin(). Me gusta, porque esta función se puede proporcionar para todos los tipos iterables que no vienen con los métodos begin()/end(). Como la mayoría de mis clases de dominio tienen interfaces que hablan en el lenguaje de dominio y no usan nombres generales como begin/end, ahora puedo proporcionar una interfaz iterable compatible con contenedores STL y base de rango para bucles sin estropear la interfaz de clase principal. Me pregunto cuál es la mejor manera de proporcionar funciones de inicio/finalización para mis propios tipos. Mi primer pensamiento fue hacerlo de la misma manera que hago con swap y escribir la función en el mismo espacio de nombres donde vive mi tipo.Cómo proporcionar funciones gratuitas de inicio/finalización para sus propios tipos

namespace My 
{ 

class Book 
{ 
public: 
    typedef std::vector<Page>::const_iterator PageIterator; 

    PageIterator FirstPage() const { return begin(pages_); } 
    PageIterator LastPage() const { return end(pages_); } 

private: 
    std::vector<Page> pages_; 
}; 

Book::PageIterator begin(const Book& b) 
{ 
    return b.FirstPage(); 
} 

Book::PageIterator end(const Book& b) 
{ 
    return b.LastPage(); 
} 

} 

¿Está bien confiar en ADL aquí, o deberían estar en el espacio de nombres estándar? Creo que otra forma es proporcionar una especialización en el espacio de nombres estándar (la sobrecarga en std no está permitida, ¿verdad?). ¿Cuál es la mejor manera en términos espaciales de buscar bucles basados ​​en rangos?

Respuesta

8

Dejaría que ADL haga su trabajo. Aunque se le permite agregar especializaciones en el espacio de nombres std, no hay una razón fuerte que se me ocurra para hacerlo cuando una función simple gratuita en su espacio de nombres es suficiente.

En particular para la gama para los bucles, los estados estándar:

§6.5.4/1 (definición de begin-expr y extremo expr):

  • de lo contrario, begin-expr y end-expr son begin(__range) y end(__range), respectivamente, donde el inicio y el final se buscan con la búsqueda dependiente del argumento (3.4.2). A los efectos de esta búsqueda de nombres, namespace std es un espacio de nombres asociado.
4

Está perfectamente bien y se recomienda "confiar" en ADL. Las funciones begin y end son parte de la interfaz de su tipo (independientemente de si son funciones independientes o no) y deben estar en el mismo espacio de nombre que su tipo.

Cuestiones relacionadas