提问人:Leon 提问时间:6/17/2020 最后编辑:Leon 更新时间:6/17/2020 访问量:875
如何在C++中转发声明std::set?
how to forward-declare std::set in c++?
问:
为了加快编译过程,我试图通过前向声明 STL 容器(例如 std::vector、std::set)来简化我的头文件......MyClass.hpp
但不能在以下代码中向前声明,而可以。std::set
std::vector
namespace std {
template<typename T, typename A> class vector;
template<typename T, typename C, typename A> class set;
};
class MyClass_t {
void showVector( std::vector<int>& );
void showSet( std::set<int>& );
}
众所周知,标头 <set> 非常长且复杂。如果我们添加到 MyClass.hpp 中,实际上每个使用 MyClass_t 的翻译单元都必须隐式包含标头 <set>。但我认为没有必要,因为不是每个使用 MyClass_t 的翻译单位都会调用 ,所以我认为简化是有道理的。#include <set>
MyClass_t::showSet
怎么做?
提前致谢,请原谅我糟糕的英语。
答:
命名空间的目的之一是分离来自不同源的代码。这通常被认为是为了避免名称冲突,但它进入了更深层次。
当库定义命名空间时,它(通常)声称完全拥有该命名空间。该库保留更改命名空间中定义的所有内容的任何和所有方面的权利,通常仅保证公共 API。这延伸到转发声明。除非另有说明,否则命名空间中的任何正向声明都是库的域,因为库可能希望在后台更改内容。一些库非常重视这一点,并提供前向声明标头,但如果没有这些标头,你就不走运了。
一般来说,不要指望能够转发任何你无法控制的内容。即使它最初有效,它也有可能在库的任何升级/补丁时中断。
继续 ,命名空间是为标准库保留的。标准库允许你在受限的情况下在命名空间中声明一些内容,但除此之外,它是禁止你的。不幸的是,对于您的目标,标准库不需要正向声明标头。如果希望代码在编译器升级后是跨平台的和/或稳定的,则需要包含完整的标头。std::set
std
std
切线:这是指定添加自己的定义是未定义行为的基础。这并不是说这些东西一定会破坏某些东西,而是语言标准不能保证究竟什么会破坏某些东西。(实际上,如果你要定义一个名为 的类,可能什么都不会爆炸。为了简单起见,应用了“未定义的行为”标签,并赋予了实现最大的自由度。namespace std
supercalifragilisticiwillmisspellthis
namespace std
评论
std::set
std::vector
std::vector
template<typename T, typename A> using vector=vectorv1<T,A>