为了加快编译过程,我试图简化我的头文件 MyClass.hpp
通过前向声明 STL 容器,例如 std::vector、std::set...
但是std::set
可以在以下代码中NOT 前向声明,而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>& );
}
众所周知, header #include <set>
到 MyClass.hpp 中,实际上每个使用 MyClass_t 的翻译单元都必须隐式包含 header MyClass_t::showSet
,所以我认为简化是有道理的。
怎么做?
提前致谢,请原谅我糟糕的英语。
最佳答案
命名空间的目的之一是分隔来自不同来源的代码。这通常被认为是为了避免名称冲突,但它涉及更深层次。
当库定义命名空间时,它(通常)声称完全拥有它。该库保留更改命名空间中定义的所有内容的任何和所有方面的权利,通常只保证公共(public) API。这扩展到前向声明。除非另有说明,否则 namespace 中的任何前向声明都是库的域,因为库可能希望在幕后进行更改。一些图书馆认真对待这一点并提供前向声明 header ,但如果没有这些,你就不走运了。
一般而言,不要指望能够转发声明任何您无法控制的内容。即使它最初可以工作,它也有可能在库的任何升级/补丁中中断。
转到 std::set
,std
命名空间是为标准库保留的。标准库允许您在受限情况下在 std
命名空间中声明一些内容,但除此之外,您不能这样做。不幸的是,对于您的目标,标准库不需要前向声明 header 。如果您希望您的代码在编译器升级后是跨平台的和/或稳定的,您将需要包含完整的 header 。
切线:这是指定将您自己的定义添加到 namespace std
是未定义行为的基础。并不是说这样的东西一定会破坏某些东西,而是语言标准不能保证到底什么东西会破坏东西。 (实际上,如果您要在 namespace std
中定义一个名为 supercalifragilisticiwillmisspellthis
的类,可能什么都不会爆炸。)为了简单起见,应用了“未定义行为”标签和实现被赋予最大的自由。
关于c++ - 如何在 C++ 中转发声明 std::set?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62420613/