2

Please consider the following code:

template<class basic_ios_type>
class basic_ios_adaptor;

template<template<typename, class> class basic_ios_type, typename char_type, class traits_type>
class basic_ios_adaptor<basic_ios_type<char_type, traits_type>>
    : public basic_ios_type<char_type, traits_type>
{
public:
    typedef basic_ios_type<char_type, traits_type> base_type;

    basic_ios_adaptor(base_type const& other)
        : base_type(other)
    {
    }
};

The only available constructor is a copy constructor which takes a const reference to the base type. Example usage:

std::ofstream                    x(std::ofstream(""));  // ok
basic_ios_adaptor<std::ofstream> y(std::ofstream(""));  // error

Visual C++:

'std::basic_ios<_Elem,_Traits>::basic_ios' : cannot access private member declared in class 'std::basic_ios<_Elem,_Traits>'

Intel:

no instance of constructor "std::basic_ofstream<_Elem, _Traits>::basic_ofstream [with _Elem=char, _Traits=std::char_traits]" matches the argument list

Could anybody explain to me why this isn't working?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0xbadf00d
  • 17,405
  • 15
  • 67
  • 107

4 Answers4

4

You can't copy streams, because their copy constructor is private (or more specifically, the copy ctor from basic_ios).

See also this question.

Community
  • 1
  • 1
Xeo
  • 129,499
  • 52
  • 291
  • 397
4

STL streams cannot be copy constructed, thats your problem.

Node
  • 3,443
  • 16
  • 18
1

As has been said, standard streams are not copiable. However, in C++0x, they are moveable. Depending on what compiler/setting you are using, that is likely the behavior you are seeing. ofstream x(std::ofstream("x")); creates a temporary ofstream, and then moves that temporary into the named ofstream. This is perfectly legal. However, in your code, you define a copy constructor, so no move can take place. Copies are still forbidden, so the compiler stops you.

So, for your class, you would also have to move, not copy. ios_base_adaptor(base_type&& other) : ofstream(std::move(other)) { }

Dennis Zickefoose
  • 10,791
  • 3
  • 29
  • 38
0

Okay, what I want to achieve is the possibility to create any basic_ios<> class I derive from. So, in my example I just wanted to create a ofstream for the specified file.

It's possible in the following way:

template<template<typename, class> class basic_ios_type, typename char_type, class traits_type>
class basic_ios_adaptor<basic_ios_type<char_type, traits_type>>
    : public basic_ios_type<char_type, traits_type>
{
public:
    typedef basic_ios_type<char_type, traits_type> base_type;

    template<class create>
    basic_ios_adaptor(create& create)
    {
        create(static_cast<base_type*>(this));
    }
};

It should be safte to pass a pointer to the base class, because at this stage it's already allocated and constructed.

Usage:

struct construct
{
    void operator()(std::ofstream* o) { 
        *o = std::ofstream("file");
    }
};

construct c;
basic_ios_adaptor<std::ofstream> y(c);

Any other workaround?

0xbadf00d
  • 17,405
  • 15
  • 67
  • 107