Proporcionar acceso a la colección de clases abstractas.

Estoy diseñando una interfaz (una clase abstracta) en C ++ que implementa una especie de estructura de árbol: cada instancia tiene cero, uno o más hijos. Los niños también son instancias de la interfaz.

Por lo general, pienso en una interfaz para no excluir implementaciones particulares. Por ejemplo, los métodos no deben devolver referencias, ya que obliga a la implementación a almacenar el valor en algún lugar. Esto excluiría las implementaciones que recalculan el valor en cada llamada; o envoltorios que transforman el valor devuelto de alguna manera.

Sin embargo, con esta interfaz, no estoy seguro de cuál es la mejor manera de proporcionar acceso a los hijos de una instancia. Hasta ahora, he encontrado dos opciones:

class Interface { public: virtual ~Interface() = default; // IDEA 1: return a collection of references. virtual auto getChildren() const -> std::vector<std::reference_wrapper> = 0; // IDEA 2: accept a visitor. virtual void visitChildren(const std::function &visitor) const = 0; }; 

Mi pregunta: ¿cuál es la mejor * manera de proporcionar acceso a una colección de clases abstractas? Otras ideas y enfoques son muy apreciados (por ejemplo, un enfoque basado en iteradores, si es posible).

* Cualquiera o todas las siguientes propiedades: la más idiomática, la más flexible, la más escalable, la más mantenible, la más intuitiva, la semánticamente más fuerte, …

Dejando a un lado la discusión de su diseño como demasiado similar a Java. Si quieres estar cerca de C ++ idiomático, ve a los iteradores:

 class Interface { class iterator_impl { virtual ~iterator_impl() = default; // Fill the rest }; public: class iterator { std::unique_ptr _impl; iterator(std::unique_ptr impl) : _impl(std::move(impl)) {} public: Iterface& operator*() { //forward to _impl } }; virtual iterator begin() = 0; virtual iterator end() = 0; }; 

Después de suministrar el protocolo de iterador completo, se puede utilizar una Interface& en el código idiomático de C ++:

 void foo(Interface& interface) { for(auto& i : interface) { //Do stuff } }