2

Дело обстоит следующим образом, у меня в отдельном заголовочном файле образовалась такая ситуация:

#pragma once;
namespace sdk {
 template <typename T>
 class list final {
  ...
 }
}

В другом заголовочном файле у меня образовалась ситуация ещё лучше:

#pragma once
#include "list.hpp"
namespace File {
 sdk::list<some_class> List() {
  ...
 }
}

Методы внутри каждого из заголовочных файлов вынесены в отдельный .cpp файл.

Использую "Visual Studio 2019", получаю вот такие ошибки со стороны IDE : LNK1120; LNK2001. На самом деле уже не знаю что делать, пробую всё подряд, но хотелось бы сохранить созданную структуру. Прошу высшие умы помочь с осознанием ошибки, поскольку информации на данную тему я не нашёл.

osm1um
  • 23
  • 3
    Что-то у меня ощущение, что не с тем у вас ошибки связаны - у вас ошибки линковки, а не компиляции. Надо смотреть, что у вас и как сделано - мало ли, вдруг у вас реализация ваших шаблонов в .cpp вынесена... – Harry Oct 02 '19 at 19:14
  • Нужен [mcve] - что-то, что мы можем скомпилировать и получить те же ошибки. – HolyBlackCat Oct 02 '19 at 19:17
  • Да, мои шаблоны вынесены в отдельный .cpp файл, это проблема? – osm1um Oct 02 '19 at 19:19
  • Из того, что вы привели, никаких определенных выводов о причинах ошибок сделать нельзя. Пространства имен, как таковые, тут ни при чем. – AnT stands with Russia Oct 02 '19 at 19:20
  • Проблема скорее всего в том что я вынес оприделение методов из класса - шабона в .cpp файл, у меня уже были раньше с этим проблемы. Как сказал Harry: "у вас ошибки линковки". Об этом мне говорит сама IDE. Это нужно делать как-то по особенному? – osm1um Oct 02 '19 at 19:25
  • Да, перенос оприделения методов прямо под объявления помогли! Но как это понимать? Есть какие-то особенные правила по поводу оприделения методов шаблонных классов? – osm1um Oct 02 '19 at 19:31
  • Вы, когда отвечаете в комментариях конкретному человеку - вставляйте его имя, предваренное @ - тогда ему придет уведомление. Понимаете, я вам написал (оказалось, верно понял проблему :)) и все - с чего мне возвращаться к этому вопросу и смотреть, не ответили ли вы что-то? А написали бы вы @Harry, я бы получил уведомление и продолжил работу с вами... – Harry Oct 05 '19 at 04:57

2 Answers2

1

Насколько я знаю, нельзя выносить шаблонные сущности в cpp-файлы, поскольку компилятор не сможет найти код, который ему инстанциировать. Перенеси реальзиции в hpp-файлы.

Qwertiy
  • 123,725
  • Спасибо, ответы и метод экспериметального тыка мне помог, но мне всё ещё интересно, этого вообще никак не избежать? – osm1um Oct 02 '19 at 19:34
  • @osm1um: Если вы хотите пользоваться всеми прелестями шаблонов (в частности - автоматическим инстанцированием), то - никак не избежать. Если же вы хотите определять шаблоны в .cpp файлах, то инстанцировать вам их придется явно вручную. Но это уже совсем другая история. – AnT stands with Russia Oct 04 '19 at 17:47
1

Просто попробуйте поставить себя на место компилятора. Есть описание шаблона - все объявления. скажем,

template<class T>
void somefunc(T t);

И есть вызов у вас в одном .cpp-файле

somefunc(1);

Компилятор знает, что где-то будет реализация, и создает в этом месте указание, что линкер тут должен вызвать функцию somefunc<int> - код ее он не знает (откуда?...)

Потом он смотрит второй .cpp-файл с реализацией. Но он не знает, что нужно скомпилтровать somefunc<int> - почему именно его, а не somefunc<char> или somefunc<mySuperClass>? Никаких указаний на это нет.

Потом приходит очередь линкера - и он видит, что должен вызвать somefunc<int>, но ее нет ни в одном объектном файле.

Так понятнее?

Вы можете указать в файле с реализацией, что надо обязательно скомпилировать ее для типа int. Но получается глупо - как только вы что-то делаете в одном файле, вам нужно тут же не забыть дописать другой.

Так что лучше просто делайте, как все - реализацию шаблонов в заголовочных файлах.

Mikhajlo
  • 12,592