extern Template from function in Class

144
28 июля 2019, 08:50

Пробую унести из декларации класса Template в реализацию, все попытки приводят к ругани компилятора, не совсем понимаю как работает в этом случае extern

a.hpp

 class A
 {
    public:
       template<typename T> bool func1(T *val);
       extern template <> bool func1<char>(char *val);
       extern template <> bool func1<wchar_t>(wchar_t *val);

a.cpp

  template<typename T>
  A::func1(T *val) {.. реализация..}

test.cpp

  char *val = ...alloc();
  A a = new A();
  a->func1(val);

В мануалах вроде так-же, но ошибок это инциирует море..

Answer 1

Не совсем понятно, что вы такое пытаетесь выписать. Синтаксис template <> - это синтаксис явной специализации. Но в явной специализации не может быть такого extern.

Если это попытка выполнить явное инстанцирование, то в синтаксисе явного инстанцирования не должно быть никаких <>. Ключевое слово extern в явном инстанцировании говорит о том, что это лишь предварительное объявление данного явного инстанцирования, а само явное инстанцирование будет выполнено вами где-то в одном из файлов реализации. Располагаться такое объявление должно за пределами класса

// a.hpp
class A
{
public:
   template<typename T> bool func1(T *val);
};
extern template bool A::func1<char>(char *val);
extern template bool A::func1<wchar_t>(wchar_t *val);

Еще раз: это никак не отменяет необходимости выполнять само явное инстанцирование в .cpp файле (то же самое без extern). Там, где видно определение инстанцируемого метода

// a.cpp
template<typename T>
bool A::func1(T *val) { /* реализация */ }
template bool A::func1<char>(char *val);
template bool A::func1<wchar_t>(wchar_t *val);

Предварительное объявление явного инстанцирования с extern - необязательный шаг. Это делается чисто ради оптимизации процесса трансляции, когда такая оптимизация возможна и нужна.

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

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

READ ALSO
Обнуление массива в Си

Обнуление массива в Си

Как правильно обнулить массив? Речь о любых типах массива, будь то символьный, целочисленный, динамический и тп Если способов несколько то желательно...

203
Символьный массив и перевод из двоичной системы в 10-ую [закрыт]

Символьный массив и перевод из двоичной системы в 10-ую [закрыт]

Есть символьный массив, в которые вводятся числа 0 и 1Нужно с помощью функции перевести элементы символьного массива из двоичной системы...

135
Rapidjson. Чего хочет SetString и как ему угодить?

Rapidjson. Чего хочет SetString и как ему угодить?

Использую RapidjsonВозникла нужда изменять строку

151
На чем сделан интерфейс в программе Kaspersky antivirus?

На чем сделан интерфейс в программе Kaspersky antivirus?

Хочу вас спросить, я недавно увидел на википедии, что Kaspersky написан на c++, скажите пожалуйста, как они создали интерфейс? WinApi, Qt, или что-то другое?

126