Using ofstream in STL list

Why the following code failed ?
And how should I modified
( Compiler : Qt5 + clang64 )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <fstream>
#include <list>

using namespace std;

class X
{
public:
    ofstream out ;
} ;

int main()
{

    list<X> xz ;
    list<X>::iterator xi ;
    X x ;

    x.out.open( "./xyz1.txt" ) ;
    xz.push_back( x ) ;

    x.out.open( "./xyz2.txt" ) ;
    xz.push_back( x ) ;

    for( xi = xz.begin() ; xi != xz.end() ; ++xi )
    {
        (*xi).out << "Hello World" << endl ;
    }

    return 0;
}


3 error messages are

/usr/include/c++/4.2.1/bits/basic_ios.tcc:192: error: base class 'std::ios_base' has private copy constructor
  extern template class basic_ios<char>;
                        ^

/usr/include/c++/4.2.1/bits/ostream.tcc:326: error: no matching constructor for initialization of 'basic_ios<char, std::char_traits<char> >'
  extern template class basic_ostream<char>;
                        ^~~~~~~~~~~~~

/usr/include/c++/4.2.1/bits/fstream.tcc:892: error: base class 'basic_streambuf<char, std::char_traits<char> >' has private copy constructor
  extern template class basic_filebuf<char>;
                        ^


Thanks
AFAIK all STL streams are non-copyable.
Yes, it seems the problem is that file stream can't be copied while calling push_back()
Last edited on
The C++ streams aren't copyable, but they are movable (since C++11). The following compiles with clang++ and LLVM libc++ standard library and runs on my linux just fine:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <fstream>
#include <list>
#include <utility>

using namespace std;

class X
{
public:
    ofstream out ;
} ;

int main()
{
    list<X> xz ;

    X x ;
    x.out.open( "./xyz1.txt" ) ;
    xz.push_back( move(x) ) ;

    X x2 ;
    x2.out.open( "./xyz2.txt" ) ;
    xz.push_back( move(x2) ) ;

    for(auto& x: xz)
        x.out << "Hello World\n";
}


If you're stuck with GNU or another library that didn't implement the C++11 I/O streams yet, use pointers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <fstream>
#include <list>
#include <utility>
#include <memory>

using namespace std;

class X
{
public:
    unique_ptr<ofstream> out ;
    X(const char* arg) : out(new ofstream(arg)) {}
} ;

int main()
{
    list<X> xz ;

    X x("./xyz1.txt");
    xz.push_back( move(x) ) ;

    xz.push_back( X("./xyz2.txt")) ;

    xz.emplace_back("./xyz3.txt") ;

    for(auto& x: xz)
        *(x.out) << "Hello World\n";
}
Last edited on
Topic archived. No new replies allowed.