-4

Let this be the example code:

object o1(//parameters);
object o2(//parameters);
object o3(//parameters);
object *v[3];

using std::cout; //video output
ofstream of;     //save on file

//let's suppose

v[0]=&o1;
v[1]=&o2;
v[2]=&o3;
for (int i=0;i<3;i++) {
    v[i]->view(cout);
    v[i]->save(of);
}

view function is just a video print function of parameters of the class, while save function saves parameters of the class on a file. The question is, if i declare std::ostream; and ostream os; why can't I use v[i]->view(os) to have video output? If I use v[i]->view(os) it says:

'std::basic_ostream<_CharT, _Traits>::basic_ostream() [with _CharT = char; _Traits = std::char_traits<char>]' is protected

And while that's true for video output, for the saving function it is not, it works, just as intended in the code. Can someone explain? sorry if i made it long

  • 3
    Can we see the code that doesn't work, including how `view` is defined ([mcve] please)? – NathanOliver Mar 11 '19 at 14:02
  • 1
    None of the code you've shown mentions `std::ostream`. The error message is coming from some other code. Post **that code**. But the problem is fairly clear from the description. `std::ostream` is intended to be used as a base class for output streams. `std::ostream os;` is not intended to work, and the compiler rightly complains. – Pete Becker Mar 11 '19 at 14:06
  • `std::ostream` is just an interface class, you need a subclass (such as `ofstream` or `ostringstream`) to do something useful. The error you got is a message that only subclasses can invoke the `ostream` constructor, which hints at "look for a subclass". – Botje Mar 11 '19 at 14:07
  • Possible duplicate of [Why is protected constructor raising an error this this code?](https://stackoverflow.com/questions/2393325/why-is-protected-constructor-raising-an-error-this-this-code) – Robert Andrzejuk Mar 11 '19 at 14:19
  • btw `std::cout` is an `ostream` – 463035818_is_not_an_ai Mar 11 '19 at 14:27
  • @user463035818 -- white that's true, it's not helpful. `std::cout` is part of the implementation, and it can rely on internal details of the standard library implementation that ordinary programmers cannot. – Pete Becker Mar 11 '19 at 15:42
  • @PeteBecker maybe not that helpful to find a solution, but helpful to fix the misunderstanding that manifests in the question title ;) – 463035818_is_not_an_ai Mar 11 '19 at 15:44
  • Please provide the function declaration of `object::view` and `object::save`. – Robert Andrzejuk Mar 17 '19 at 13:40

1 Answers1

0

The issues:

1) If the view function is defined as:

void view(std::ostream output, std::string text) // (1)
{
    output << text;
}

And used:

view(std::cout, "Hello, World!"); // (2)

Then an error message is given by the compiler:

In MSVC:

error C2280: 'std::basic_ostream<char,std::char_traits<char>>::basic_ostream(const std::basic_ostream<char,std::char_traits<char>> &)': attempting to reference a deleted function

GCC:

error: use of deleted function 'std::basic_ostream<_CharT, _Traits>::basic_ostream(const std::basic_ostream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]'

Clang:

error: call to deleted constructor of 'std::ostream' (aka 'basic_ostream<char>')


2) For the declaration

std::ostream os;

The following error message is displayed:

MSVC:

error C2512: 'std::basic_ostream<char,std::char_traits<char>>': no appropriate default constructor available

GCC:

error: 'std::basic_ostream<_CharT, _Traits>::basic_ostream() [with _CharT = char; _Traits = std::char_traits<char>]' is protected within this context

Clang:

error: calling a protected constructor of class 'std::basic_ostream<char>'


The reason:

This is all according to the specification of std::basic_ostream

There is no definition for a default constructor - so a variable of the type std::ostream cannot be created, without specific constructor parameters.

And as C++ Reference says about the std::basic_ostream copy constructor:

The copy constructor is protected, and is deleted. Output streams are not copyable.


Explanation:

1) So the problem is that in (2) the parameter std::cout is been passed to a function which is defined in (1) to copy the std::ostream to the variable output.

But the definition of the class says that the copy constructor cannot be used, so the compiler gives an error message.

2) In the case of creating the variable os - it is not giving any constructor parameters, there is no default constructor, so the compiler gives an error message.


How to fix this?

1) In the declaration of the function change the definition to take a reference (&) of std::ostream as a parameter:

void view(std::ostream& output, std::string text) // (1)

This allows it to use the original object instead of making a copy (which the copy is not allowed).


2) If a variable is required, then also a reference should be used;

std::ostream& out = std::cout;
Robert Andrzejuk
  • 5,076
  • 2
  • 22
  • 31