Компилятор, не создающий шаблонный ostream << оператор
-
23-08-2019 - |
Вопрос
У меня есть класс, определенный в 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;
}