Typedef y ostream operador para un std::vector
Pregunta
He creado una clase Cromosoma, que terminó por ser simplemente un contenedor para que el vector con un ostream operador, así que me he decidido a typedef vector lugar.Sin embargo, estoy teniendo problemas con la plantilla ostream operador...Es esta la mejor manera de ir sobre ella?(Yo he visto un par de enfoques y han fallado en obtener cualquier trabajo)
template<typename G>
class Chromosome {
public:
typedef typename std::vector<G> type;
typedef typename std::pair<type *,type *> ptr_pair;
};
template<typename G> //line 19 below:
std::ostream& operator<<(std::ostream& os, const Chromosome<G>::type& chromosome) {
for(auto iter = chromosome.begin(); iter != chromosome.end(); ++iter)
std::cout << *iter;
return os;
}
En el momento en que el error que voy es:
chromosome.h:19: error: expected unqualified-id before ‘&’ token
chromosome.h:19: error: expected ‘)’ before ‘&’ token
chromosome.h:19: error: expected initializer before ‘&’ token
Saludos.
Solución
Desafortunadamente, no hay una manera correcta de hacer esto porque el compilador no puede deducir el tipo de G
a partir de la declaración de la función
template<typename G>
std::ostream& operator<<(std::ostream& os, const typename Chromosome<G>::type& chromosome);
La razón es que si se especializan Chromosome
para los diferentes tipos, usted podría terminar en una situación en la que el compilador no podía inferir inequívocamente G
.Por ejemplo:
template <typename G> class Chromosome {
public:
typedef std::vector<G> type; // No typename needed here, BTW
};
template <> class Chromosome<int> {
public:
typedef std::vector<double> type;
};
Ahora, ¿qué pasaría si usted hizo esto?
vector<double> v;
cout << v << endl;
El compilador no puede saber si G
es double
o int
en este caso, debido a que ambos Chromosome<int>
y Chromosome<double>
han vector<double>
como su tipo anidado.
Para solucionar esto, usted tendrá que utilizar explícitamente el tipo de vector<G>
como el argumento:
template<typename G>
std::ostream& operator<<(std::ostream& os, const std::vector<G>& chromosome);
Por desgracia, en realidad no hay una mejor manera de hacer esto.No es realmente un defecto en el lenguaje, ya que hay una buena razón para prohibir, pero en realidad le impide hacer lo que quieres en este contexto.
Otros consejos
El miembro typedef type
es un dependiente de nombre de:su significado depende del parámetro de plantilla G
.Usted necesidad de utilizar un typename
para indicar al compilador que type
los nombres de un tipo:
const typename Chromosome<G>::type&
Para la explicación completa, considere la posibilidad de leer el Desbordamiento de Pila en C++ FAQ artículo, Donde poner la "plantilla" y "typename" en dependiente de los nombres de.
Como @templatetypedef alude a ello en los comentarios, mientras que esto permitirá que el código se compile, no "trabajo" que le permiten insertar un std::vector<G>
en un std::ostream
porque type
es en un nondeduced contexto.
La forma más sencilla de declarar la sobrecarga y obtener el comportamiento esperado es el uso de std::vector<G>
directamente como el tipo de argumento:
template<typename G>
std::ostream& operator<<(std::ostream& os, const std::vector<G>& chromosome)