【问题标题】:Vector of streams in C++11C++11 中的流向量
【发布时间】:2014-07-18 23:18:28
【问题描述】:

以下代码

vector<ofstream> v;
v.emplace_back("file1.txt");
v.emplace_back("file2.txt");
for (int i = 0, ilen = v.size(); i < ilen; ++i)
    v[i] << "Test" << i << endl;

在 VS2013 中编译良好,但在 GCC 中失败并显示不可读的消息。看来VS2013的行为是正确的。

  • 我不复制流,而是在原地创建它;
  • vector 变得足够大时,内容应该移动到一个新的内存区域。

虽然我在标准中找不到合适的地方来说明这一点。有人可以引用吗?

【问题讨论】:

  • 您介意分享这条不可读的消息吗?
  • 什么版本的 gcc,带有哪些标志?
  • @doctorlove 当然。 ideone.com/0X0vsO。很可能它正在尝试调用复制构造函数。
  • @karim 那是ideone 的编译器。手册说它是 gcc-4.8.1,但在它的标志上没有说太多。
  • 这里还有关于流和移动的其他详细信息:stackoverflow.com/questions/20774587/…

标签: c++ c++11 vector stream standards


【解决方案1】:

如果你向下滚动到 clang 抛出的 end of the errors,你会看到这个:

/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/basic_ios.h:66:23: note: copy constructor of 'basic_ios<char, std::char_traits<char> >' is implicitly deleted because base class 'std::ios_base' has an inaccessible copy constructor

这是 gcc 长长的错误列表中的对应行:

/usr/include/c++/4.8/bits/basic_ios.h:66:11: note: 'std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)' is implicitly deleted because the default definition would be ill-formed:

     class basic_ios : public ios_base

这是因为 libstdc++ 缺少 basic_ios 的移动构造函数,如状态页面上列出的 here 所示。

27.5 | iostreams 基类 |部分 | basic_ios 上缺少移动和交换操作。

还有here's 相关的bugzilla。如果你使用 libc++,你的代码 compiles with clang

一个更简单的例子,从错误报告中复制而来,也是fails to compile

#include <sstream>
#include <utility>
std::stringstream getss(){
   std::stringstream q;
   return std::move(q);
}

【讨论】:

    【解决方案2】:

    解决您的问题:

    template<typename T, typename...Args>
    std::unique_ptr<T> make_unique(Args&&...args) {
      return std::unique_ptr<T>( new T(std::forward<Args>(args)...) );
    }
    

    如果你讨厌输入ofstream:

     template<typename...Args>
     std::unique_ptr<std::ofstream> make_up_ofstream(Args&&...args) {
       return make_unique<std::ofstream>(std::forward<Args>(args)...);
     }
    

    给你:

    std::vector<std::unique_ptr<std::ofstream>> v;
    v.emplace_back(make_up_ofstream("file1.txt"));
    v.emplace_back(make_up_ofstream("file2.txt"));
    for (int i = 0, ilen = v.size(); i < ilen; ++i)
      *(v[i]) << "Test" << i << endl;
    

    这很接近,不是吗?

    这让我想写make_up 来推断您分配给它的unique_ptr 的类型:

    // dense boilerplate, obsolete in C++1y:
    template<unsigned...>struct indexes{typedef indexes type;};
    template<unsigned Max,unsigned...Is>struct make_indexes:make_indexes<Max-1,Max-1,Is...>{};
    template<unsigned...Is>struct make_indexes<0,Is...>:indexes<Is...>{};
    template<unsigned Max>using make_indexes_t=typename make_indexes<Max>::type;
    
    template<typename T>using type=T;
    
    template<typename... Args>
    struct up_maker {
      std::tuple<Args...> args;
      template<class T, class...Ds, unsigned...Is>
      std::unique_ptr<T,Ds...> helper( indexes<Is...> ) && {
        return std::unique_ptr<T,Ds...>( new T(std::forward<Args>( std::get<Is>(args) )...) );
      }
      template<class T, class...Ds>
      operator type<std::unique_ptr<T,Ds...>>() && {
        return std::move(*this).helper<T,Ds...>( make_indexes_t< sizeof...(Args) >{} );
      }
      explicit up_maker( Args&&... args_in ):args( std::forward<Args>(args_in)... ) {}
      up_maker( up_maker const& ) = delete;
      up_maker( up_maker && ) = default;
      up_maker& operator=( up_maker const& ) = delete;
      up_maker& operator=( up_maker && ) = default;
    };
    
    template<typename...Args>
    up_maker<Args...> make_up( Args&&... args ) {
      return up_maker<Args...>( std::forward<Args>(args)... );
    }
    

    如果我写得对,可以在你的代码中去掉更多样板:

    std::vector<std::unique_ptr<std::ofstream>> v;
    v.emplace_back(make_up("file1.txt"));
    v.emplace_back(make_up("file2.txt"));
    for (int i = 0, ilen = v.size(); i < ilen; ++i)
      (*v[i]) << "Test" << i << std::endl;
    

    ...很多代码只是为了摆脱两个_ofstream,但这很有趣。

    live example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-15
      • 1970-01-01
      • 2018-09-30
      • 2018-01-17
      • 1970-01-01
      • 2014-04-15
      • 1970-01-01
      • 2015-08-21
      相关资源
      最近更新 更多