【问题标题】:C++ how to make tuple of ofstreams?C ++如何制作ofstreams的元组?
【发布时间】:2016-08-12 20:04:49
【问题描述】:

我有三个 std::ofstream 对象,我将它们放在如下函数中并在 main() 中使用它们。编译时收到很多错误消息,有人可以帮我解决这个问题吗?

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

std::tuple<std::ofstream, std::ofstream, std::ofstream>
set_ofstream_tuple() {
   std::ofstream out1("out1.txt", std::ofstream::out);
   out1 << "this is out1.txt" << std::endl;
   std::ofstream out2("out2.txt", std::ofstream::out);
   out2 << "this is out2.txt" << std::endl;
   std::ofstream out3("out3.txt", std::ofstream::out);
   out3 << "this is out3.txt" << std::endl;

   return std::make_tuple(out1, out2, out3);
}

int main() {
  std::ofstream out1, out2, out3;
  std::tie(out1, out2, out3) = set_ofstream_tuple();
  /// make use of there ofstreams more here
}

【问题讨论】:

  • 请发布您的错误信息,以帮助其他人赢得时间。
  • 这不是问题,但std::ofstream::outofstream 构造函数的第二个参数的默认值。你不需要写它。 std::ofstream out1("out1.txt"); 就足够了。
  • @PeteBecker 你是对的。

标签: c++ tuples ofstream


【解决方案1】:

这一行:

return std::make_tuple<out1, out2, out3>;

很奇怪。你想做什么? :)

std::make_tuple 是一个函数,它从它的参数中生成一个元组:

return std::make_tuple(std::move(out1), std::move(out2), std::move(out3));

注意std::move,这些是必需的,因为您不能复制std::ofstream

【讨论】:

  • 那里也加入三个std::moves。
  • @0x499602D2 谢谢,忘记了 :)
  • @Rakete1111 我仍然在使用 std::move() 和 std::forward_as_tuple() 时遇到错误。您的编译是否使用此 sn-p ?我使用了 -std=c++11。
  • 这里的前几行错误...我用 return std::make_tuple(std::move(out1), std::move(out2), std::move(out3));
【解决方案2】:

问题是您在返回之前将不可复制的ofstream 复制到元组中。

一种解决方案是在返回之前将 ofstreams 移动到元组中:

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

std::tuple<std::ofstream, std::ofstream, std::ofstream>
set_ofstream_tuple() 
{
   std::ofstream out1("out1.txt", std::ofstream::out);
   out1 << "this is out1.txt" << std::endl;
   std::ofstream out2("out2.txt", std::ofstream::out);
   out2 << "this is out2.txt" << std::endl;
   std::ofstream out3("out3.txt", std::ofstream::out);
   out3 << "this is out3.txt" << std::endl;

   return std::make_tuple(std::move(out1), std::move(out2), std::move(out3));
}

int main() {
  std::ofstream out1, out2, out3;
  std::tie(out1, out2, out3) = set_ofstream_tuple();
  /// make use of there ofstreams more here

}

证明:on godbolt

另一种解决方案是在创建过程中使用元组作为主存储:

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

std::tuple<std::ofstream, std::ofstream, std::ofstream>
set_ofstream_tuple() 
{
  auto streams = std::make_tuple(std::ofstream("out1.txt", std::ofstream::out),
                                 std::ofstream("out2.txt", std::ofstream::out),
                                 std::ofstream("out3.txt", std::ofstream::out));

  auto& out1 = std::get<0>(streams);
  auto& out2 = std::get<1>(streams);
  auto& out3 = std::get<2>(streams);

  out1 << "this is out1.txt" << std::endl;
  out2 << "this is out2.txt" << std::endl;
  out3 << "this is out3.txt" << std::endl;

  return streams;
}

int main() {
  std::ofstream out1, out2, out3;
  std::tie(out1, out2, out3) = set_ofstream_tuple();
  /// make use of there ofstreams more here

}

从 c++17 开始,我们将能够使用即将推出的 std::optional 避免空的 ofstreams 的冗余构造(此处使用 std::experimental 进行演示):

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

#include <experimental/optional>

std::tuple<std::ofstream, std::ofstream, std::ofstream>
set_ofstream_tuple() 
{
  auto streams = std::make_tuple(std::ofstream("out1.txt", std::ofstream::out),
                                 std::ofstream("out2.txt", std::ofstream::out),
                                 std::ofstream("out3.txt", std::ofstream::out));

  auto& out1 = std::get<0>(streams);
  auto& out2 = std::get<1>(streams);
  auto& out3 = std::get<2>(streams);

  out1 << "this is out1.txt" << std::endl;
  out2 << "this is out2.txt" << std::endl;
  out3 << "this is out3.txt" << std::endl;

  return streams;
}

int main() {
  std::experimental::optional<std::ofstream> out1, out2, out3;
  std::tie(out1, out2, out3) = set_ofstream_tuple();
  /// make use of there ofstreams more here

}

【讨论】:

  • 不幸的是,第一种和第二种解决方案不适用于我使用的编译器版本上的 C++11 或 C++14。
  • @user3658306 编译器版本是多少?
  • @user3658306 添加了godbolt的链接来证明这一点。
  • godbolt 显示与我得到的相同的编译失败。这是一个很酷的工具!谢谢分享。
  • 使用 C++17,您将使用结构化绑定而不是 optional ... auto [out1, out2, out3] = set_ofstream_tuple();
猜你喜欢
  • 2022-01-24
  • 1970-01-01
  • 2016-03-23
  • 1970-01-01
  • 1970-01-01
  • 2020-01-21
  • 1970-01-01
  • 1970-01-01
  • 2018-05-15
相关资源
最近更新 更多