c++ - 如何在 C++ 中转发声明 std::set?

标签 c++ set std forward-declaration

为了加快编译过程,我试图简化我的头文件 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 的翻译单元都会调用 MyClass_t::showSet ,所以我认为简化是有道理的。

怎么做?

提前致谢,请原谅我糟糕的英语。

最佳答案

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

当库定义命名空间时,它(通常)声称完全拥有它。该库保留更改命名空间中定义的所有内容的任何和所有方面的权利,通常只保证公共(public) API。这扩展到前向声明。除非另有说明,否则 namespace 中的任何前向声明都是库的域,因为库可能希望在幕后进行更改。一些图书馆认真对待这一点并提供前向声明 header ,但如果没有这些,你就不走运了。

一般而言,不要指望能够转发声明任何您无法控制的内容。即使它最初可以工作,它也有可能在库的任何升级/补丁中中断。


转到 std::setstd 命名空间是为标准库保留的。标准库允许您在受限情况下在 std 命名空间中声明一些内容,但除此之外,您不能这样做。不幸的是,对于您的目标,标准库不需要前向声明 header 。如果您希望您的代码在编译器升级后是跨平台的和/或稳定的,您将需要包含完整的 header 。

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

关于c++ - 如何在 C++ 中转发声明 std::set?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62420613/

相关文章:

c++ - C++ 是否有标准方法对两个 std::sets、 vector 等进行三态比较?

c++ - mem_func 和 for_each 用法

c++ - 入门级 <iostream> hell (p)

c++ - 赋值运算符的返回类型是什么?

行为类似于 __COUNTER__ 宏的 C++ 结构

c++ - 控制命名空间中的访问?

python - 如何测试 Python 中唯一项目的多个集合?

arrays - 如何在Kotlin中将Set(HashSet)转换为数组?

algorithm - 哪种实现最适合 Prim 的算法,使用 Set 还是 Priority Queue?为什么?

c++ - 将字符串流转换为 STL 容器