1

我在头文件中声明了一个函数模板。这个函数是一个归档器,它应该支持通过项目实现的其他几种类型(类)。这个想法是有一个基本模板声明,然后每个类都专门针对自己的类型。

// 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是一种绝望的行为。

4

3 回答 3

5

只是不要使用模板:

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

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

这样就简单多了。只需进行不合格的调用archive()并确保此重载声明在与 ADL 相同的命名空间中,Header 然后让 ADL 发挥它的魔力。

于 2015-10-21T18:16:52.957 回答
2

为什么要使用函数模板?

你说:

这个想法是有一个基本模板声明,然后每个类都专门针对自己的类型。

如果函数模板没有默认实现,那么拥有一个根本没有意义。您可以使用:

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)
{
}

更新,以回应OP的评论

我尝试了以下方法来模拟您的情况。

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

该程序已成功构建。

于 2015-10-21T18:20:01.887 回答
0

在这种情况下,我认为,重载就可以了。您在这里并不需要模板。

void archive(Archiver & archiver, const Header & obj);
void archive(Archiver & archiver, const Footer & obj);
void archive(Archiver & archiver, const Whatever & obj);
于 2015-10-21T18:23:37.127 回答