【问题标题】:Using std::setw() without <iomanip> header使用没有 <iomanip> 标头的 std::setw()
【发布时间】:2021-09-17 18:16:12
【问题描述】:

即使我没有包含&lt;iomanip&gt;,这段代码怎么可能编译?

#include <iostream>
#include <fstream>

int main()
{
    std::cout << std::setw(5) << "test" << std::endl;
    return 0;
}

编译:

clang++ test.cpp

但如果没有&lt;fstream&gt;,它会抛出错误:

test.cpp:5:20: error: no member named 'setw' in namespace 'std'
        std::cout << std::setw(5) << "test" << std::endl;
                     ~~~~~^
1 error generated.

在我朋友的 Mac 上,这两种情况都会引发错误。

【问题讨论】:

  • 在您的系统上,iomanip 包含在 fstream 标头中,因此它可以工作,但这是实现定义的,因此另一个系统上的另一个编译器(-version)可以在没有 iomanip 的情况下定义 fstream。
  • iostream 和/或fstream 中的一个或两个本身可以递归地包含多个头文件等。您可以使用-H 选项到clang++(或g++)来找出包含iomanip 的确切位置。

标签: c++ fstream clang++ setw


【解决方案1】:

标准 C++ 头文件可能包含其他标准头文件,如果这便于实现的话。您的&lt;fstream&gt; 作为实现细节包括&lt;iomanip&gt;,但在Mac 上它显然不包括在内。

规则:包含您需要的内容,不要依赖意外包含。这不会强加开销;标准标头都可以安全地包含多次。

【讨论】:

    【解决方案2】:

    标头在内部包含自身,具体取决于标准库实现。

    除非您包含某个文件,否则该标准不保证符号是未定义的 - 相反,它保证如果您包含某个符号,它将被定义。

    在这种情况下,fstream 标头在内部包含恰好也具有 std::setw 定义的代码。

    在您的编译器上编译的代码是您的标准库实现的特殊性。

    在我们当前的项目中,缺少标头是构建失败的常见原因之一(构建在 Windows 上有效,但在 Mac 上无效,反之亦然)。

    通常,在代码中包含您需要的所有内容的指定标头,即使代码在没有包含的情况下也可以编译。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-20
      • 1970-01-01
      • 2013-10-21
      • 2011-07-16
      相关资源
      最近更新 更多