перегружен класс шаблона и извлечение вставки - PullRequest
4 голосов
/ 09 ноября 2010

Как сделать так, чтобы оператор вставки (<<) и / или извлечения (>>) был перегружен в классе шаблона, БЕЗ того, чтобы он был встроенным.Я хотел бы иметь оператор << или >> в качестве класса друга.Я знаю, как сделать это встроенным примером встроенного в матричном классе

friend ostream& operator<<(ostream& ostr, const Matrix<T>& inputMatrix)
{
   ...
   // create the ostr
   return ostr;
}

, но я бы хотел, чтобы код находился вне определения шаблона.

g ++ сказал мне добавить <> после имени функции, что я и сделал, но когда я попытался создать экземпляр матрицы типа SOMETYPE, он выдал ошибку, что не знал, как извлечь или вставить для этого типа.

Ответы [ 3 ]

2 голосов
/ 09 ноября 2010

Попробуйте что-то вроде:

template <typename T> class Matrix;
template <typename T> std::ostream& operator<<(std::ostream& ostr, const Matrix<T>& m);

template <Typename T>
class Matrix
{
    public:

        friend ostream& operator<< <T> (ostream& ostr, const Matrix<K>& inputMatrix);
};

// This must be in the same translation unit as the class definition!
template<typename T>
ostream& operator<<(ostream& ostr, const Matrix<T>& inputMatrix)
{
   // ...
   return ostr;
}

Ссылка на единицу перевода

переиздано с учетом комментариев, сделанных aschepler и dribeas.

1 голос
/ 09 ноября 2010

Если вы действительно хотите определить оператор извне и подружиться только с экземпляром оператора, который совпадает по типу с этим экземпляром шаблона, правильный синтаксис:

template <typename T> class test; // forward declare template class
template <typename T>              // forward declare the templated operator
std::ostream& operator<<( std::ostream&, test<T> const & );

template <typename T>
class test {                      // define the template
   friend std::ostream& operator<< <T>( std::ostream&, test<T> const & ); // befriend
};
template <typename T>              // define the operator 
std::ostream& operator<<( std::ostream& o, test<T> const & ) {
   return o;
}

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

Также обратите внимание, что у компилятора есть небольшие различия в отношении поиска.В случае, когда функция встроена в определение класса, компилятор не найдет эту функцию , если только один из аргументов на самом деле не относится к типу шаблона, поэтому он эффективно уменьшает видимость и количестворабота, которую должен выполнить компилятор (если шаблонное operator<< определено вне класса, компилятор найдет его в качестве кандидата для разрешения перегрузки во всех местах, где он находит a << b, только чтобы отбросить его во всех случаях, когдавторой аргумент не является test<T> (и он будет показывать шаблонный оператор в качестве кандидата во всех сообщениях об ошибках, где он не может соответствовать operator<<, который уже является достаточно длинным списком).

1 голос
/ 09 ноября 2010

Поместите код в заголовок, вне определения класса.Или поместите его в файл .tcc и добавьте его внизу заголовка.

...