如何在 C++ 中前向声明 std::set?

2024-04-23

为了加快编译过程,我正在尝试简化我的头文件MyClass.hpp通过前向声明 STL 容器,例如 std::vector、std::set...

But std::set can NOT在以下代码中进行前向声明,同时std::vector can be.

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>& );
}

众所周知,标头非常长且复杂。如果我们添加#include <set>到 MyClass.hpp 中,事实上,每个使用 MyClass_t 的翻译单元都必须隐式包含标头 。但我认为这是没有必要的,因为并不是每个使用 MyClass_t 的翻译单元都会调用MyClass_t::showSet,所以我认为简化是有道理的。

怎么做?

预先感谢,请原谅我糟糕的英语。


命名空间的目的之一是分离来自不同来源的代码。这通常被认为是为了避免名称冲突,但它涉及更深的层次。

当库定义名称空间时,它(通常)声称完全拥有它。该库保留更改命名空间中定义的所有内容的任何和所有方面的权利,通常仅保证公共 API。这延伸到转发声明。除非另有说明,命名空间中的任何前向声明都是库的域,因为库可能想要在幕后更改内容。有些库认真对待这一点并提供前向声明标头,但如果没有这些,你就不走运了。

一般来说,不要指望能够转发声明任何您无法控制的内容。即使它最初可以工作,但在对库进行任何升级/修补时也可能会损坏。


继续到std::set, the std命名空间是为标准库保留的。标准库使您能够在std命名空间在受限制的情况下,但在其他情况下它对您来说是禁止的。不幸的是,对于您的目标来说,标准库不需要前向声明标头。如果您希望代码在编译器升级后跨平台和/或稳定,则需要包含完整的标头。

切线:这是指定将您自己的定义添加到的基础namespace std是未定义的行为。并不是说这样的东西一定会破坏某些东西,而是语言标准不能保证到底什么会破坏东西。 (实际上,如果您要定义一个名为supercalifragilisticiwillmisspellthis in namespace std,可能什么都不会爆炸。)为了简单起见,应用了“未定义行为”标签,并给予实现最大的自由度。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 C++ 中前向声明 std::set? 的相关文章

随机推荐