9

I am using an abstract class std::ostream. There is the following reference:

std::ostream &o = std::cout; 

If any condition is met I need to initialize o so that the output will be redirected to std::cout. If not, output will be redirected to the file

if (!condition)
    o = file; //Not possible 

How to correctly write the code?

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
Johnas
  • 1,263
  • 3
  • 12
  • 23
  • This problem is more about reseating references than the std::ostream, I would suggest changing the title. Because the question is a good one. – daramarak Aug 02 '11 at 09:38
  • You need to understand reference in c++ just means an alias. So once the reference has been initialized , any further operator= to it means just change the original item the reference has been referring to. A good example can be found in Steve's answer below. – RoundPi Aug 02 '11 at 09:50

2 Answers2

16

Either:

std::ostream &o = condition ? std::cout : file;

or if there's code in between your two snippets:

std::ostream *op = &std::cout;
// more code here
if (!condition) {
    op = &file;
}
std::ostream &o = *op;

The problem isn't specifically to do with the abstract class, it's that references cannot be reseated.

The meaning of the expression o = file isn't "make o refer to file", it is "copy the value of file into the referand of o". Luckily for you, std::ostream has no operator=, and so it fails to compile and std::cout isn't modified. But consider what happens with a different type:

#include <iostream>

int global_i = 0;

int main() {
    int &o = global_i;
    int file = 1;
    o = file;
    std::cout << global_i << "\n"; // prints 1, global_i has changed
    file = 2;
    std::cout << o << "\n"; // prints 1, o still refers to global_i, not file
}
Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • @Steve: The problem is not only that references cannot be reset, in OP's case `o=file` will not compile also, [because `std::ostream` or any stream in C++ cannot be assigned (or copied).](http://stackoverflow.com/questions/6010864/why-copying-stringstream-is-not-allowed/6010930#6010930) – Nawaz Aug 02 '11 at 09:59
  • @Nawaz: I mention that, but IMO it's not a problem. I don't think the questioner actually wants to redirect `stdout` itself to a file, which is the only effect I can think `operator=` would have if it did exist. – Steve Jessop Aug 02 '11 at 11:00
5

You can't reseat a reference.

This is an alternative though :

std::ostream &o = (!condition) ? file : std::cout;
Sander De Dycker
  • 16,053
  • 1
  • 35
  • 40