为什么 `<< std::endl` 不调用我希望它调用的运算符?

2023-12-25

我正在寻找一种同时写入文件和控制台的解决方案。我找到了一个很好的解决方案here https://stackoverflow.com/a/13665106/4117728.

由于我正在使用 C++11 之前的版本,因此我必须对 Lightness Races in Orbit 中的代码进行一些小更改:

#include <iostream>
#include <fstream>
#include <string>

struct OutputAndConsole : std::ofstream
{
    OutputAndConsole(const std::string& fileName)
       : std::ofstream(fileName.c_str())   // constructor taking a string is C++11
       , fileName(fileName)
    {};

    const std::string fileName;
};

template <typename T>
OutputAndConsole& operator<<(OutputAndConsole& strm, const T& var)
{
    std::cout << var;    
    static_cast<std::ofstream&>(strm) << var;
    return strm;
};

除了一件小事让我困惑之外,它工作得很好。如果我像这样使用它:

int main(){
    OutputAndConsole oac("testLog.dat");
    double x = 5.0;
    oac << std::endl;
    static_cast<OutputAndConsole&>(oac << "foo \n" << x << "foo").operator<<(std::endl);  
    oac << "foo" << std::endl;
}

然后所有的std::endl当它们正确显示在文件中时,控制台上的输出将被忽略。我的猜测是当我使用std::endl the ostream::operator<<被调用,它将打印到文件但不打印到控制台。该行与static_cast<OutputAndConsole&>是我外行尝试调用正确的运算符,但仍然只有换行符\n出现在控制台上。

Why for std::endl调用了错误的运算符?

我怎样才能调用正确的呢?

PS: 我知道我可以用\n没有问题,但我仍然想知道这里发生了什么以及如何解决它。


struct OutputAndConsole : std::ofstream
{
  // ...
};

template <typename T>
OutputAndConsole& operator<<(OutputAndConsole& strm, const T& var);

正如其他人提到的,std::endl是一个模板函数。模板函数不是一个值,这只是一个名字。

如果您尝试将模板函数传递给需要兼容签名的函数,则模板函数可以转换为值。这是not如果传递给模板函数,则转换为值T or const T&,因为模板函数的名称代表了一个整体host可能的值。

Because std::endl不是您自定义编写的有效参数operator<<,它看起来在别处。它找到了std::ofstream's operator<<它通过显式函数指针获取 io 操纵器函数。

那个有效,它可以转换endl到那个函数指针类型!所以,它高兴地这样称呼它。

要解决此问题,请添加operator<<过载至OutputAndConsole它采用 io 操纵器函数指针。

最简单的方法是编写一个辅助函数:

template <class T>
void output_to(OutputAndConsole& strm, const T& var)
{
  std::cout << var;    
  static_cast<std::ofstream&>(strm) << var;
};

然后两个<<重载:

template<class T>
OutputAndConsole& operator<<(OutputAndConsole& strm, const T& var) {
  output_to(strm, var);
  return strm;
}
OutputAndConsole& operator<<(OutputAndConsole& strm, std::ostream& (*var)(std::ostream&)) {
  output_to(strm, var);
  return strm;
}

这导致std::endl寻找匹配的模板<<.

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

为什么 `<< std::endl` 不调用我希望它调用的运算符? 的相关文章

随机推荐