没有std命名空间

Gle*_*len 2 c++ compiler-construction namespaces std

我们有一个合理大小的C++应用程序,在这个阶段已经很老了,所以它有一些怪癖.

其中一个怪癖是它如何处理使用预标准化标准库的C++编译器.有一个头文件可以解决符合标准的编译器和这个不兼容的编译器之间的任何差异.由于各种原因,我们不能/不想停止支持这个编译器.

#include <vector>
#include <set>
#if defined(NO_STD_LIB)
    #include <iostream.h>
#else
    #incude <iostream>

    using std::string;
    using std::cout;
    using std::vector;
    using std::cout;
#endif
Run Code Online (Sandbox Code Playgroud)

你使用如下

#include stl.h
int main() {
    vector<string> foo;
    .....
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这种方法有两个主要问题:

  1. 包含std.h的每个编译单元都必须编译许多不需要的代码(我们试图尽可能地减少编译时间)
  2. 全局命名空间受到std命名空间中通常存在的所有内容的污染.

作为代码清理项目的一部分,我真的想解决这两点.第一个确实是这样做的更重要的原因.

因为我们必须支持这个旧的编译器,所以我们的代码总是要避免将名称与它在标准库中公开的东西冲突,所以第2点并不真正相关,尽管我希望看到一个解决方案,当/如果我们最终可以放弃对它的支持.

到目前为止,我的想法是将超级标题分解为一组较小的标题.例如stl_vector,stl_iostream,stl_set等.这样我们只能包含我们感兴趣的标准库的部分.这些文件名遵循std头的模式,但有一个容易搜索的前缀.因此,当需要转储有问题的编译器时,搜索前缀并将其删除会很简单.

我认为这将很容易解决问题1.

我真正的问题是解决问题2.我想做这样的事情

#if defined(NO_STD_LIB)
    #include <iostream.h>
    #define std
#else
    #include <iostream>
Run Code Online (Sandbox Code Playgroud)

然后我们可以编码如下:

#incude "stl_iostream"

int main() {
  std::string foo("bar");
  std::cout << foo << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

这几乎奏效了.没有标准命名空间的地方#define std使std :: string分解成:: string,生活很好.

然后我尝试使用.cc文件,该文件使用了可怕的"using namespace std;" 我得到一个编译错误,因为它变成"使用命名空间",所以这显然是行不通的.

现在显然我可以禁止人们编写"using namespace std;",但是尽管它应该在头文件中避免,但它有时在.cc文件中很有用,你们正在大量使用大量的STL类.

所以,最后,问题.是否存在处理此问题的标准习惯用法.或者,如果没有标准的方法来处理这个问题,那么你使用什么技巧来支持使用预标准标准库的编译器.

我曾经想过使用预编译的头来解决编译速度问题,但是我们针对不同的编译器,并且努力让它们在所有这些编译器中工作可能意味着它不值得花时间去做.

建议我放弃不合格编译器的答案可能很受欢迎,但不会被接受,因为这是我们现在不能做的事情.

Tho*_*ini 16

你可以试试:

#if defined(NO_STD_LIB)
namespace std {
    using ::string;
    using ::cout;
    using ::vector;
    using ::cout;
}
#endif
Run Code Online (Sandbox Code Playgroud)

然后std::string会工作.

如果using namespace ::;指令存在于该语言中会好得多; 但事实并非如此.