Question

J'ai créé un chromosome de classe qui a fini par être simplement un wrapper pour Vector avec un opérateur OSstream, j'ai donc décidé de Typedef Vector à la place. Cependant, j'ai des problèmes avec l'opérateur d'osstream modèle ... Est-ce la meilleure façon de procéder? (J'ai vu quelques approches et j'ai réussi à faire fonctionner)

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;
}

Pour le moment, l'erreur que j'obtiens est:

chromosome.h:19: error: expected unqualified-id before ‘&’ token
chromosome.h:19: error: expected ‘)’ before ‘&’ token
chromosome.h:19: error: expected initializer before ‘&’ token

Acclamations.

Était-ce utile?

La solution

Malheureusement, il n'y a pas de moyen propre de le faire car le compilateur ne peut pas déduire le type de G de la déclaration de fonction

template<typename G>
std::ostream& operator<<(std::ostream& os, const typename Chromosome<G>::type& chromosome);

La raison en est que si vous deviez vous spécialiser Chromosome Pour différents types, vous pourriez vous retrouver dans une situation où le compilateur ne pouvait pas déduire sans ambiguïté G. Par exemple:

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;
};

Maintenant, que se passerait-il si vous faisiez cela?

vector<double> v;
cout << v << endl;

Le compilateur ne peut pas dire si G est double ou int Dans ce cas, parce que les deux Chromosome<int> et Chromosome<double> ont vector<double> comme leur type imbriqué.

Pour résoudre ce problème, vous devrez utiliser explicitement le type vector<G> Comme l'argument:

template<typename G>
std::ostream& operator<<(std::ostream& os, const std::vector<G>& chromosome);

Malheureusement, il n'y a vraiment pas de meilleure façon de le faire. Ce n'est pas vraiment un défaut dans la langue, car il y a une bonne raison de l'interdire, mais cela vous empêche de faire ce que vous voulez dans ce contexte.

Autres conseils

Le membre Typedef type est un nom dépendant: sa signification dépend du paramètre de modèle G. Vous devez utiliser un typename pour dire au compilateur que type Nomme un type:

const typename Chromosome<G>::type&

Pour l'explication complète, envisagez de lire l'article de FAQ C ++ FAQ à débordement de pile, Où mettre le «modèle» et «typename» sur les noms dépendants.

Comme @TemplateTypeDef fait allusion aux commentaires, alors que cela permettra au code de compiler, cela ne "fonctionnera" pas pour vous permettre d'insérer un std::vector<G> en un std::ostream car type est dans un contexte non conduit.

Le moyen le plus simple de déclarer la surcharge et d'obtenir le comportement attendu est d'utiliser std::vector<G> directement comme type d'argument:

template<typename G>
std::ostream& operator<<(std::ostream& os, const std::vector<G>& chromosome)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top