正确前向声明完全专用的模板类
Correct forward declaration of fully specialized template classes
假设我有以下一堆文件:
泛型:复杂的模板类
#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;
};
客户端.cpp:客户端代码可能知道Generic.h
和Special.h
#include "Client.h"
#include "Special.h"
Client::Client()
{
map["343"] = 2;
}
主.cpp:
#include <Client.h>
int main(int argc, char**args) {
Client c;
return 0;
}
GenericMap
表示没有前向声明的模板类。对于某些用户来说,完全专业化的版本SpecialMap
GenericMap
就足够了,为了便于使用,使用typedef
。
现在Client
使用内部SpecialMap
,但头文件应该只声明SpecialMap
的前向声明。
遗憾的是,以下文件将无法编译。不知何故,发布的前瞻声明就足够了。什么是正确的?
我很抱歉列表很长,但这是我能想到的最小的非工作示例。
在评论中,您澄清说您实际上并不是指C++专业化。你只是在问typedef:
typedef GenericMap<std::string, int, std::map> SpecialMap;
故事到此为止。这声明SpecialMap
是一个typedef
,一个类型别名。任何需要使用SpecialMap
的翻译单元都需要包含此类型定义。只有这个定义。不需要做任何其他事情。它不需要以任何其他方式声明。它是一个别名。搜索/替换typedef
别名与其基础类型会产生完全相同的结果。在一个翻译单元中声明的typedef
仅在该翻译单元中可见。其他翻译单元没有捷径可以将typedef
导入其范围。
在您的客户端中:
#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
模板类,这里只是向前声明的。
- .cpp和.h文件中的模板专用化声明
- 专用模板是否需要专用声明?
- 在实例化封闭类模板之后,我们可以声明模板类成员的部分专用化吗
- C++模板专用化中的声明范围
- 显式专用化 - 模板 ID 与任何模板声明都不匹配
- 静态声明专用类的接口指针数组
- 模板类专用化:模板 ID 与任何模板声明都不匹配
- enable_if在类声明之外实现的方法专用化
- 声明一个模板函数,将模板类友元的两个对象(仅)带到这两个专用化
- 为什么在标题上的结构中声明的模板不违反 ODR 并且专用化会违反 ODR
- 类模板专用化的前向声明
- 了解模板的声明、定义和专用化
- 如何为非类型模板类的专用化定义声明之外的方法
- 声明无法解决"实例化后的显式专用化"错误
- 如何声明模板的友元函数的专用化
- C++11:模板专用化的 constexpr 成员的标准参考需要额外声明
- 在友元模板专用化的声明中不允许使用Constexpr
- 在何处声明类成员模板的部分专用化
- 模板类中专用函数的声明
- C++函数模板专用声明和模板参数;无 vs. <> vs. <type>