完全专业化的模板功能

时间:2015-10-21 18:10:57

标签: c++ templates gcc template-instantiation

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

// 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. 直接在头文件中实现,通常建议用于模板:我得到&#34;多重定义&#34;
  2. 在.cpp文件中的实现没有标题声明:从另一个编译单元调用方法时我得到undefined reference
  3. 那么实现这个是正确的呢?

    编辑:

    最初我决定使用模板,因为反向过程,取消归档。基本上我可以写unarchive<Header>()而不是unarchive_header(),这似乎更合适。

    我相信我还应该提到我使用Android Studio和Gradle构建系统来编译它,这就是我使用gcc而不是g ++的原因。我还给了gcc以下编译器标志:

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

    -fpermissive是一种绝望的行为。

3 个答案:

答案 0 :(得分:5)

不要使用模板:

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

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

这样简单得多。只需对archive()进行无条件调用,并确保在与Header相同的命名空间中声明此重载,并让ADL发挥其魔力。

答案 1 :(得分: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

该计划已成功建立。

答案 2 :(得分:0)

在这种情况下,我认为,重载只是诀窍。你真的不需要这里的模板。

void archive(Archiver & archiver, const Header & obj);
void archive(Archiver & archiver, const Footer & obj);
void archive(Archiver & archiver, const Whatever & obj);