c++ - 正确的完全特化模板类的前向声明

标签 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;
};

Special.h:定义上述模板类的完全专用版本,简化易用性。

#pragma once

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

typedef GenericMap<std::string, int, std::map> SpecialMap;

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

#pragma once

class SpecialMap; // Wrong forward declaration

struct Client {
    Client();
    SpecialMap* map;
};

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

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

Client::Client()
{
    map["343"] = 2;
}

ma​​in.cpp:

#include <Client.h>

int main(int argc, char**args) {
    Client c;
    return 0;
}

GenericMap 表示没有前向声明的模板类。对于某些用户来说,GenericMap 的完全专用版本 SpecialMap 应该就足够了,为了便于使用,使用了 typedef

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

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

对于冗长的 list ,我深表歉意,但这是我能想到的最小的非工作示例。

最佳答案

在评论中,您澄清说您实际上并不是指 C++ 特化。您只是在询问 typedef:

typedef GenericMap<std::string, int, std::map> SpecialMap;

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

在你的 Client.h 中:

#include <Special.h>

那是您定义此 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;

这将是定义 typedef 别名所需的最低限度。任何实际需要使用它的东西,都需要 #include 不仅仅是这个头文件,还有你的 Generic.h 头文件,它实际上定义了 GenericMap 模板类,这里只是前向声明。

关于c++ - 正确的完全特化模板类的前向声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38244994/

相关文章:

C++ 应用程序以 143 退出代码终止——这是什么意思?

c++ - 使用 constexpr 返回指针

c++ - 在模板类之外定义友元函数的正确方法是什么?

c++ - g++ 的 liblastfm 编译错误

c++ - 在 C++ 中运行 cmd 命令

c++ - 为什么必须在哪里放置 “template”和 “typename”关键字?

c++ - 键入特征以从运算符(operator)处获取提升结果

javascript - .load() 传递 POST 请求

c++ - 在标题中转发声明并包含在 CPP 中?

c++ - 将耦合类拆分为单独的 header