Не работает обьявление шаблона класса в заголовочном файле с определением методов в отдельном файле реализации

117
05 сентября 2019, 06:00

Например у меня есть Test.h в котором определен шаблон класса Test и в Test.cpp определены методы и конструкторы класса причем неявным образом,а вот уже где нибудь в main.cpp я инициализирую Test<int> testValue. Ничего не сработает, так как компилятор не знает, как определить мои Type в Test.cpp. Как можно "схитрить" ( Не используя дополнительного третьего файла типа .inl или что нибудь еще)

Test.h

#ifndef Test
#define Test
template <class Type>
class Test
{
private:
    Type value;
public:
    Test(Type valueOfUser);
    Type getValue();
};
#endif // Test

Test.cpp

#include "Test.h"
template <typename Type> Test<Type>::Test(Type valueOfUser): value(valueOfUser) {}
template <typename Type> Type Test<Type>::getValue () { return value; }

main.cpp

#include "Test.h"
intt main()
{
  Test<int> test;
  test.getValue();
  return 0;
}
Answer 1

Есть один способ, но неудобный.

В test.cpp можно явно инстанцировать class Test для Type = int, добавив в конец файла:

template class Test<int>;

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

Это - самое последнее средство. Намного лучше будет послушать @Harry и просто держать дефиниции шаблонных функций в заголовочных файлах.

Answer 2

Уж сколько раз твердили миру... (с)

Не помещайте определения шаблонных функций/классов в отдельные .cpp-файлы. Размещайте все только в заголовочных файлах - иначе инстанцирования не происходит, вот и имеем, что имеем.

Совет от Страуструпа (A Tour of C++, adv. 7-6):

Раздельной компиляции шаблонов нет: вы должны включать с помощью директивы #include определения шаблонов в каждую единицу трансляции, которая их использует.

Вот подумайте сами - откуда при компиляции файла Test.cpp компилятору знать, что (с каким параметром шаблона) будет инстанцироваться в другом файле?

А в этом другом файле (main.cpp) - откуда знать, как инстанцировать шаблон, если нет доступа к коду реализации?

Обходной путь - указать в файле реализации шаблона явное инстанцирование необходимых типов

template class Test<конкретный_тип>;

возможен, но очень уж он неудобный - в следующий раз в main.cpp понадобится класс для нового типа, и надо будет тут же вносить его в test.cpp. Еще хуже, если какой-то тип станет ненужен, но будет продолжать инстанцироваться и линковаться.

Answer 3

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

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

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

READ ALSO
Перегрузка оператора присваивания C++ без использования strcpy

Перегрузка оператора присваивания C++ без использования strcpy

Изучаю C++Буду очень признателен за любую помощь

130
В каком порядке вызываются слоты?

В каком порядке вызываются слоты?

Если к одному сигналу подключены множество слотов, то в каком порядке оны вызываются?

125
Как с помощью QT вывести на монитор 10-битное изображение?

Как с помощью QT вывести на монитор 10-битное изображение?

Недавно появился снэпшот Qt 513, в котором у QImage стал доступен формат QImage::Format_Grayscale16

116
Задача перебора значений

Задача перебора значений

Попалась следующая задачаИмеется входное значение частоты Fin и выходное Fout

98