Функция шаблона для полной специализации

У меня есть шаблон функции, объявленный в заголовочном файле. Эта функция является архиватором, который должен поддерживать несколько других типов (классов), реализованных в рамках проекта. Идея состоит в том, чтобы иметь базовое объявление шаблона, которое каждый класс затем специализирует на своих собственных типах.

// 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, Я пробовал и другие комбинации:

  1. Реализация непосредственно в заголовочном файле, как это обычно рекомендуется для шаблонов: я получаю «множественное определение»
  2. Реализация в .cpp файле без объявления в шапке: получаю undefined reference при вызове метода из другого модуля компиляции

Так что является правильным для реализации этого?

Редактировать:

Изначально я решил пойти с шаблонами из-за обратного процесса, разархивирования. В принципе я мог бы написать unarchive<Header>() вместо unarchive_header() который казался более подходящим.

Я считаю, что я должен также упомянуть, что я компилирую это с помощью Android Studio и системы сборки Gradle, поэтому я использую gcc, а не g ++. Я также дал gcc следующие флаги компилятора:

-std=gnu++11 -fexceptions -fpermissive -lstdc++

-fpermissive был акт отчаяния.

1

Решение

Просто не используйте шаблоны:

// Header.h
void archive(Archiver & archiver, const Header & obj);

а также

// Header.cpp
void archive(Archiver & archiver, const Header & obj)
{
// Code here
}

Намного проще. Просто сделайте безоговорочный вызов archive() и убедитесь, что эта перегрузка объявлена ​​в том же пространстве имен, что и Header и пусть ADL сделает свое волшебство.

5

Другие решения

Зачем использовать шаблон функции?

Вы сказали:

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

Если шаблон функции не имеет реализации по умолчанию, его вообще не имеет смысла. Вы можете просто использовать:

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

Программа была успешно построена.

2

В этом случае я думаю, что перегрузка просто делает свое дело. Вам не нужны шаблоны здесь.

void archive(Archiver & archiver, const Header & obj);
void archive(Archiver & archiver, const Footer & obj);
void archive(Archiver & archiver, const Whatever & obj);
0
По вопросам рекламы [email protected]