C ++标准库:如何为cout,cerr,cin和endl编写包装器?

时间:2010-05-21 04:24:57

标签: c++ iostream

我不喜欢using namespace std,但我也厌倦了必须在每个std::coutcin和{cerr前面输入endl {1}}。所以,我想给他们更短的新名字:

// STLWrapper.h

#include <iostream>
#include <string>

extern std::ostream& Cout;
extern std::ostream& Cerr;
extern std::istream& Cin;
extern std::string&  Endl;

// STLWrapper.cpp

#include "STLWrapper.h"

std::ostream& Cout = std::cout;
std::ostream& Cerr = std::cerr;
std::istream& Cerr = std::cin;
std::string _EndlStr("\n");
std::string& Endl = _EndlStr;

这很有效。但是,上面有什么问题我错过了吗?有没有更好的方法来实现同样的目标?

2 个答案:

答案 0 :(得分:84)

Alex已经给你an answer如何在语法上解决这个问题。但是,我想指出关于这个问题的另外两个论点:

  1. 无论您是使用使用指令using namespace std)还是其较小的邪恶妹妹,使用声明({{1重载可能会导致令人讨厌的惊喜。与 花费半夜调试 来查找your code called std::distance() instead of your own distance() function相比,输入using std::cout并不是很麻烦,只是因为你犯了一个小错误而且{ {1}}意外地是一个更好的匹配。

  2. 一行代码 会被写入 ,但是 - 根据其生命周期 - 会被读取数十,数百和一些甚至数千次 。所以编写一行代码所花费的时间根本不重要 重要的只是读取和解释一行代码所花费的时间 即可。即使将所有正确的std::写入一行所需的时间长达三倍,如果它的读取速度只提高了10%,那么它仍然值得一试。
    因此,重要的问题是:是否更容易阅读和解释所有std::distance()或更难的代码行?来自another answer

      

    这里还有一个数据点:许多年前,我还常常发现,必须使用std::标准库中的所有内容作为前缀。然后我在一个项目中工作,在开始时决定禁止std::指令和声明,除了函数范围。你猜怎么着?我们大部分人花了很长时间才习惯编写前缀,经过几个星期后,我们大多数人甚至同意它实际上使代码更具可读性。 (这有一个原因: 无论你喜欢更短或更长的散文都是主观的,但前缀客观上增加了代码的清晰度。 不仅是编译器,而且你也是,找到更容易看到引用的标识符。)

         

    十年来,该项目增长了数百万行代码。由于这些讨论一次又一次地出现,我曾经很奇怪(允许的)函数范围std::实际上在项目中的使用频率。我找了它的来源,只发现了一两个地方使用它。对我而言,这表明, 一旦尝试过,开发人员就没有发现using足够痛苦 使用指令甚至每100kLoC 即使它在哪里允许使用

    我觉得很遗憾你会发现每本书和教程都会跳过using,因为这会让人习惯于以这种方式阅读代码。当我教C ++几年(在上述经历之后)时,我告诉我的学生我不想在他们的代码中看到任何std::指令或声明。 (该规则的唯一例外是std::,BTW,为了让using获取命名空间using std::swap之外的重载,您需要它。)一旦他们习惯了,他们并不介意,当被问到这个问题时,他们说他们发现代码没有让swap(a,b)前缀混淆。 有些人甚至将std前缀添加到他们从没有它的书籍或教程中输入的代码中

  3. 结论:键入std::让每个人都对此有所了解是多么困难?到现在为止,我已经做了大约15年了,我根本不会错过std::

答案 1 :(得分:59)

为什么不

using std::cin;
using std::cout;

等等?然后在您的代码中,您可以使用cincout等,而不会意外地将std名称空间的所有其余部分注入代码中。