C++如何同时计算和写入

C++ how to cout and write at the same time

阅读此文后:C++ Writing to file and Console Output at the same time with simple code,我正在尝试编写一个函数来处理我在 for 循环中的内容。但是我不知道如何将这样的一段代码作为参数传递给函数:setw(3) << right << get<0>(*it_party) << setw(9) << "" 以便 cout 和 file 都可以使用它。

The helper function I am trying to write:
void print(std::ostream &os1, std::ostream &os2, const [I don't know what to put in here])
{
    os1 << the argument; // cout
    os2 << the argument; // file
}

ofstream file;
file.open("test.txt");

for (auto it_party = parties_.begin(); it_party != parties_.end(); ++it_party) {
    cout << setw(3) << right << get<0>(*it_party) << setw(9) << "";
    file << setw(3) << right << get<0>(*it_party) << setw(9) << "";
    cout << setw(7) << left << get<1>(*it_party) << setw(1) << "";
    file << setw(7) << left << get<1>(*it_party) << setw(1) << "";
    ...
    ...
  }

如果你想像那样将输出串在一起,你可能会发现使用某种 "tee" class:

更容易
class Tee {
private:
    std::ostream &os1, &os2;
public:
    Tee(std::ostream &os1, std::ostream &os2) : os1(os1), os2(os2) { }

    template <typename T>
    Tee& operator<<(const T &thing) {
        os1 << thing;
        os2 << thing;
        return *this;
    }
};

这将采用模板参数,因此它不会关心您传递的是 right 还是 setw(3)。您可以像这样使用它:

Tee t(std::cout, std::cout);
t << setw(10) << "right" << " Thing" << setw(9);

您可以使用 std::stringstream 轻松完成此操作。我不知道 get<>() 是什么,但这是一个基本示例:

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

void fn(std::string output) {

    std::ofstream file("file.txt");

    std::cout << output;
    file << output;

}

int main() {

    std::stringstream buffer;
    buffer << "some random text" << std::endl;

    fn(buffer.str());

    return 0;
}

不幸的是,您不能将所有这些东西仅作为一个参数传递。但是有一些高级技术可以帮助您,例如 variadic templates and C++17 fold expressions.

可变参数模板是一项功能,例如,它允许您在编译时传递未知数量的不同类型的参数。您可以在标准库中看到一些此类示例,例如 std::tuple.

折叠表达式是与前一个功能结合使用的另一个功能。它允许您编写非常简单的可变参数模板代码:

template<typename ...Args>
void printer(const Args &... args) {
    (std::cout << ... << args) << '\n';
}

这里我们看到一个函数,它接受一些 const & 到一些参数(我们不知道它们的数量或不同类型),但是我们有像 args 这样奇特的东西,一个参数pack,代表我们的参数,和 Args 作为它们的类型一起 "packed";

您可以使用它来将任意参数传递给您的流:

template<typename ...Args>
void printer(const Args &... args) {
    (std::cout << ... << args);
    (file << ... << args);
}

此解决方案还有一些其他需要改进的地方,例如perfect forwarding,但这些有待进一步研究。