У меня есть шаблон функции, объявленный в заголовочном файле. Эта функция является архиватором, который должен поддерживать несколько других типов (классов), реализованных в рамках проекта. Идея состоит в том, чтобы иметь базовое объявление шаблона, которое каждый класс затем специализирует на своих собственных типах.
// Archiver.h
template <class T> void archive(Archiver & archiver, const T & obj);
Этот метод не имеет реализации. Теперь я создаю класс (скажем, Header
) и я хочу, чтобы это было в архиве. Поэтому я намерен специализировать метод. Вот что у меня сейчас:
// Header.h
extern template void archive(Archiver & archiver, const Header & obj);
Я объявляю функцию как extern
потому что я реализую это в файле .cpp
// Header.cpp
template <> void archive(Archiver & archiver, const Header & obj)
{
// Code here
}
Это дает specialization after instantiation
, Я пробовал и другие комбинации:
undefined reference
при вызове метода из другого модуля компиляцииТак что является правильным для реализации этого?
Редактировать:
Изначально я решил пойти с шаблонами из-за обратного процесса, разархивирования. В принципе я мог бы написать unarchive<Header>()
вместо unarchive_header()
который казался более подходящим.
Я считаю, что я должен также упомянуть, что я компилирую это с помощью Android Studio и системы сборки Gradle, поэтому я использую gcc, а не g ++. Я также дал gcc следующие флаги компилятора:
-std=gnu++11 -fexceptions -fpermissive -lstdc++
-fpermissive
был акт отчаяния.
Просто не используйте шаблоны:
// Header.h
void archive(Archiver & archiver, const Header & obj);
а также
// Header.cpp
void archive(Archiver & archiver, const Header & obj)
{
// Code here
}
Намного проще. Просто сделайте безоговорочный вызов archive()
и убедитесь, что эта перегрузка объявлена в том же пространстве имен, что и Header
и пусть ADL сделает свое волшебство.
Зачем использовать шаблон функции?
Вы сказали:
Идея состоит в том, чтобы иметь базовое объявление шаблона, которое каждый класс затем специализирует на своих собственных типах.
Если шаблон функции не имеет реализации по умолчанию, его вообще не имеет смысла. Вы можете просто использовать:
extern void archive(Archiver & archiver, const Header & obj);
когда тебе это нужно.
Если вы должны использовать шаблон функции
Линия
extern template void archive(Archiver & archiver, const Header & obj);
не является правильным. Это должно быть:
template <> void archive<Header>(Archiver & archiver, const Header & obj);
Реализация должна использовать одну и ту же подпись.
template <> void archive<Header>(Archiver & archiver, const Header & obj)
{
}
Обновление в ответ на комментарий ОП
Я попробовал следующее, чтобы смоделировать вашу ситуацию.
socc.h:
#pragma once
struct Archiver {};
template <class T> void archive(Archiver & archiver, const T & obj);
struct Header {};
template <> void archive<Header>(Archiver & archiver, const Header & obj);
socc.cc:
#include <iostream>
#include <string>
#include "socc.h"
int main()
{
Archiver ar;
Header obj;
archive(ar, obj);
}
socc-2.cc:
#include "socc.h"
template <> void archive<Header>(Archiver & archiver, const Header & obj)
{
}
Команда для сборки:
g++ -std=c++11 -Wall socc.cc socc-2.cc -o socc
Программа была успешно построена.
В этом случае я думаю, что перегрузка просто делает свое дело. Вам не нужны шаблоны здесь.
void archive(Archiver & archiver, const Header & obj);
void archive(Archiver & archiver, const Footer & obj);
void archive(Archiver & archiver, const Whatever & obj);