更正向前声明完全专业的模板类

Ale*_*ph0 5 c++ templates forward-declaration class-template

假设我有以下文件:

Generic.h:复杂的模板类

#pragma once

template<typename K, typename V, template<typename Key, typename Value, typename ...> typename C>
struct GenericMap
{
    C<K, V> key;
};
Run Code Online (Sandbox Code Playgroud)

Special.h:定义所提及模板类的完全专用版本,从而简化易用性。

#pragma once

#include "Generic.h"
#include <string>
#include <map>

typedef GenericMap<std::string, int, std::map> SpecialMap;
Run Code Online (Sandbox Code Playgroud)

Client.h:使用SpecialMap并定义前向声明的客户端。

#pragma once

class SpecialMap; // Wrong forward declaration

struct Client {
    Client();
    SpecialMap* map;
};
Run Code Online (Sandbox Code Playgroud)

Client.cpp:客户代码可能知道Generic.hSpecial.h

#include "Client.h"
#include "Special.h"

Client::Client()
{
    map["343"] = 2;
}
Run Code Online (Sandbox Code Playgroud)

main.cpp:

#include <Client.h>

int main(int argc, char**args) {
    Client c;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

GenericMap表示没有前向声明的模板类。对于某些用户来说SpecialMapGenericMap应当完全专业化的版本应该足够,在这里为了易于使用而使用a typedef

现在在Client内部使用SpecialMap,但是头文件应该只为声明一个前向声明SpecialMap

不幸的是,以下文件无法编译。以某种方式发布的向前声明就足够了。正确的是什么?

我为冗长的清单感到抱歉,但这是我能想到的最小的不工作示例。

Sam*_*hik 5

在注释中,您澄清了您实际上并不是在指C ++专业化。您只是在问有关typedef的问题:

typedef GenericMap<std::string, int, std::map> SpecialMap;
Run Code Online (Sandbox Code Playgroud)

这几乎就是故事的结局。这声明SpecialMap为a typedef,类型别名。任何需要使用的翻译单元都SpecialMap必须包含此类型定义。而且只有这个定义。不需要做其他任何事情。不需要以任何其他方式声明它。这是一个别名。搜索/替换typedef别名及其基础类型会产生相同的准确结果。一个typedef在一个翻译单元中声明仅在该翻译单元可见。其他翻译部门没有将其typedef导入其范围的捷径。

在您的Client.h中:

#include <Special.h>
Run Code Online (Sandbox Code Playgroud)

那是您定义this的地方typedef,这是引入此定义的唯一方法。

但是,也可能是的情况下,后者typedef是较大的头文件的一部分,并且希望仅单独提取typedef。这可以通过仅包含以下内容的头文件来完成:

#include <string>
#include <map>

template<typename K, typename V,
        template<typename Key, typename Value, typename ...>
             typename C> struct GenericMap;

typedef GenericMap<std::string, int, std::map> SpecialMap;
Run Code Online (Sandbox Code Playgroud)

这将是定义typedef别名所需的最低要求。实际需要使用它的任何东西,不仅需要#include此头文件,还需要您的Generic.h头(实际上定义了GenericMap模板类),这里仅对它进行了前向声明。