Вопрос

Я создал класс Chromosome, который в итоге оказался просто оберткой для вектора с оператором ostream, поэтому вместо этого я решил использовать typedef вектор.Однако у меня возникли проблемы с шаблонным оператором ostream...Это лучший способ сделать это?(Я видел несколько подходов, но мне не удалось заставить их работать)

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

На данный момент я получаю следующую ошибку:

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

Ваше здоровье.

Это было полезно?

Решение

К сожалению, нет чистого способа сделать это, поскольку компилятор не может определить тип G из объявления функции

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

Причина в том, что если бы вы специализировались Chromosome для разных типов вы можете оказаться в ситуации, когда компилятор не сможет однозначно вывести G.Например:

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

Итак, что произойдет, если вы это сделаете?

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

Компилятор не может определить, G является double или int в данном случае, потому что оба Chromosome<int> и Chromosome<double> иметь vector<double> как их вложенный тип.

Чтобы это исправить, вам придется явно использовать тип vector<G> в качестве аргумента:

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

К сожалению, лучшего способа сделать это действительно не существует.На самом деле это не недостаток языка, поскольку есть веская причина запретить его, но на самом деле это мешает вам делать то, что вы хотите в этом контексте.

Другие советы

Тип члена type является зависимым именем:его значение зависит от параметра шаблона G.Вам нужно использовать typename сообщить компилятору, что type называет тип:

const typename Chromosome<G>::type&

Для полного объяснения прочитайте статью часто задаваемых вопросов по Stack Overflow C++: Где разместить «шаблон» и «имя типа» для зависимых имен.

Как намекает @templatetypedef в комментариях, хотя это и позволит скомпилировать код, оно не «работает», чтобы позволить вам вставить std::vector<G> в std::ostream потому что type находится в невыведенном контексте.

Самый простой способ объявить перегрузку и получить ожидаемое поведение — использовать std::vector<G> непосредственно как тип аргумента:

template<typename G>
std::ostream& operator<<(std::ostream& os, const std::vector<G>& chromosome)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top