1

I want to achieve something like this:

#include <iostream>
#include <fstream>
#include <string>

void write(std::ofstream& o)
{
    o << "Some text..." << std::endl;
}

int main(const int argc, const char** argv)
{
    if (argc == 2){
        auto outputStream = std::ofstream(argv[1]);
        write(outputStream);
    }
    else{
        auto outputStream = std::ofstream(std::cout);
        write();
    }
}

The code doesn't compile because std::ofstream cannot be constructed from std::cout.

A viable solution is to use rdbuf() in the context pointer_to_ofstream->basic_ios<char>::rdbuf(std::cout.rdbuf()) (as provided in this entry).

Is there a better solution?

François Andrieux
  • 28,148
  • 6
  • 56
  • 87
Nestor
  • 687
  • 5
  • 12
  • 1
    I've rolled back your edit. It's important to remember that Stack Overflow questions stick around and future users may have the same problems you have just faced. Considering that, it's important to make sure the answers provided continue to make sense. Applying the fix from the answer to the question would mean that, from the perspective of a future reader, the answer doesn't apply to the question. That answer would now refer to an error that is not present in the question. – François Andrieux Aug 12 '19 at 18:07
  • Can we stop _completely changing the question_ every few minutes please, guys? Thanks. – Lightness Races in Orbit Aug 12 '19 at 18:09
  • @LightnessRacesinOrbit I tried to rollback at the same time as someone else, so my rollback rollbacked their rollback. It's back to the original state now. – François Andrieux Aug 12 '19 at 18:11

2 Answers2

5

Don't use std::ofstream in write. Use std::ostream.

void write(std::ostream& o)
{
    o << "Some text..." << std::endl;
}

Also,

 auto outputStream = std::ofstream(std::cout);
 write();

is not right. Just use.

 write(std::cout);

I'd change the first of the if block too.

if (argc == 2){
    std::ofstream outputStream(argv[1]);
    write(outputStream);
}
else{
    write(std::cout);
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 3
    @Nestor Please leave the question in it's original state. Making changes to an answer question, if it changes the meaning of the question, can be confusing for future readers. You can edit the question but be sure not the invalidate answers by doing so. – François Andrieux Aug 12 '19 at 18:04
  • Sorry about that. `write(std::cout)` works, yet I want an object which may be used later. (The formulation of the question is clearly imperfect :/ That's my first question here). – Nestor Aug 12 '19 at 18:09
  • Regarding your last edit with changes to the `if`, that's a matter of style thus opinion. For example, the original `if` is in line with the [Almost Always Auto](https://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/) style which is a valid style some developers choose to use. – François Andrieux Aug 12 '19 at 18:09
  • 1
    If you have a new question, ask a new question. This one has been answered in completion. – Lightness Races in Orbit Aug 12 '19 at 18:09
  • @FrançoisAndrieux, agreed. I think `auto x = ...;` does not make sense to me when you are constructing an object using a type. It makes sense when initializing an object from the return value of a function call. Of course, YMMV :) – R Sahu Aug 12 '19 at 18:11
  • Ok. Thanks. I'll post another question. – Nestor Aug 12 '19 at 18:15
1

You've already gotten a good answer. Here's another way to do it, which probably answers your second question:

void write(std::ostream& o) {
  o << "Some text..." << std::endl;
}

std::unique_ptr<std::ostream> stream( argc == 2
  ? std::make_unique<std::ofstream>(argv[1])
  : std::make_unique<std::ostream>(std::cout.rdbuf())
);
write(*stream);
David G
  • 94,763
  • 41
  • 167
  • 253