简体   繁体   English

完全专业化的模板功能

[英]Template function for full specialization

I have a function template declared in an header file. 我在头文件中声明了一个功能模板。 This function is an archiver which is supposed to support several other types (classes) implemented through the project. 此功能是一个归档程序,应该支持通过项目实现的其他几种类型(类)。 The idea is to have a base template declaration which each class then specialises to its own types. 这个想法是要有一个基本的模板声明,然后每个类专门针对其自己的类型。

// Archiver.h
template <class T> void archive(Archiver & archiver, const T & obj);

This method does not have an implementation. 该方法没有实现。 Now I create a class (say, Header ) and I want it to be archivable. 现在,我创建一个类(例如Header ),并且希望它可以归档。 As such, it is my intent to specialise the method. 因此,我的目的是专门研究该方法。 Here's what I have now: 这是我现在所拥有的:

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

I declare the function as extern because I implement it in the .cpp file 我将函数声明为extern因为我在.cpp文件中实现了该函数

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

This gives specialization after instantiation . specialization after instantiation给出了specialization after instantiation I've tried other combinations as well: 我也尝试了其他组合:

  1. Implementing directly in the header file, as is usually recommended for templates: I get "multiple definition" 直接在头文件中实现,通常建议使用模板:我得到“多个定义”
  2. Implementation in the .cpp file without a declaration on the header: I get undefined reference when calling the method from another compilation unit .cpp文件中的实现,而没有在标头上声明:从另一个编译单元调用该方法时,我得到undefined reference

So what is the correct of implementing this? 那么实施此方法的正确性是什么?

Edit: 编辑:

Initially I decided to go with templates because of the inverse process, unarchiving. 最初,由于逆过程,我决定使用模板进行取消存档。 Basically I could write unarchive<Header>() instead of unarchive_header() which seemed more appropriate. 基本上我可以写unarchive<Header>()代替看起来更合适的unarchive_header()

I believe I should also mention that I'm compiling this using Android Studio and the Gradle build system, which is why I'm using gcc and not g++. 我相信我还应该提到我正在使用Android Studio和Gradle构建系统进行编译,这就是为什么我使用gcc而不是g ++的原因。 I also gave gcc the following compiler flags: 我还给了gcc以下编译器标志:

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

-fpermissive was an act of despair. -fpermissive是绝望的行为。

Just don't use templates: 只是不要使用模板:

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

and

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

Much simpler that way. 这样简单得多。 Simply make an unqualified call to archive() and make sure this overload is declared in the same namespace as Header and let ADL do its magic. 只需对archive()进行无限制的调用,并确保在与Header相同的名称空间中声明此重载,然后让ADL发挥作用。

Why use a function template? 为什么要使用功能模板?

You said: 你说:

The idea is to have a base template declaration which each class then specialises to its own types. 这个想法是要有一个基本的模板声明,然后每个类专门针对其自己的类型。

If a function template does not have a default implementation, it is pointless to have one at all. 如果功能模板没有默认实现,则完全没有意义。 You can just use: 您可以使用:

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

when you need it. 当您需要时。

If you must use a function template 如果必须使用功能模板

The line 线

extern template void archive(Archiver & archiver, const Header & obj);

is not right. 是不正确的。 It needs to be: 它必须是:

template <> void archive<Header>(Archiver & archiver, const Header & obj);

The implementation needs to use the same signature. 实现需要使用相同的签名。

template <> void archive<Header>(Archiver & archiver, const Header & obj)
{
}

Update, in response to OP's comment 更新,以回应OP的评论

I tried the following to simulate your situation. 我尝试了以下方法来模拟您的情况。

socc.h: 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: socc.cc:

#include <iostream>
#include <string>

#include "socc.h"

int main()
{
   Archiver ar;
   Header obj;
   archive(ar, obj);
}

socc-2.cc: socc-2.cc:

#include "socc.h"

template <> void archive<Header>(Archiver & archiver, const Header & obj)
{
}

Command to build: 生成命令:

g++ -std=c++11 -Wall    socc.cc  socc-2.cc -o socc

The program was built successfully. 该程序已成功构建。

In this case I think, overloading simply does the trick. 我认为在这种情况下,重载就可以解决问题。 You don't really need templates here. 您实际上并不需要模板。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM