Вопрос

У меня есть класс, определенный в head как:

template <typename T> class MyClass
{
   template <typename U> friend std::ostream& operator<<(std::ostream& output, const MyClass<U>& p);
   public:
      ...
}

В файле реализации у меня есть:

template <typename U> std::ostream& operator<<(std::ostream& output, const MyClass<U>& m)
{
   output << "Some stuff";
   return output;
}

Все это выглядит довольно кошерно.Однако, когда я пытаюсь использовать этот оператор (т.е.ЗППП::cout << MyClass()), я получаю следующую ошибку компоновщика:

Undefined symbols: std::basic_ostream<char, std::char_traits<char> >& operator<< <InnerType>(std::basic_ostream<char, std::char_traits<char> >&, MyClass<InnerType> const&)

Я удивлен, что компилятор автоматически не сгенерировал это для меня...Есть какие-нибудь предложения относительно того, что я делаю не так?

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

Решение

В файле реализации у меня есть:

В этом-то и проблема.Вы не можете разделить определения шаблонов между файлами заголовка и реализации.Из-за природы шаблонов компиляторы C ++ здесь очень привередливы.Определите весь код в заголовке, чтобы он работал.

Фактически, проблема здесь в том, что все определения шаблонов должны находиться в одном модуле компиляции, потому что стандарт C ++ не определяет, как информация о шаблоне передается в разные модули.Эти блоки объединяются компоновщиком, но общие разрешаются во время компиляции (что происходит раньше)., не во время соединения.

Теоретически, стандарт C ++ определяет ключевое слово, export, чтобы справиться с этими случаями.На практике, НЕТ компилятор реализует это (за одним исключением?), и нет намерения изменять это, потому что компромисс между стоимостью и полезностью не считается достаточно хорошим.

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

Слишком много шаблонов - это работает:

#include <iostream>
using namespace std;
template <typename T> struct MyClass {

    friend ostream & operator << ( ostream & os, MyClass<T> & c ) {
        os << "MyClass\n";
        return os;
    }
};

int main() {
    MyClass <int> c;
    cout << c;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top