4

I'd like to make a pair containing two std::ostream object. I need this so that I can pass a single object to various functions instead of two std::ostream objects. I was hoping I could do this:

#include <iostream>
#include <ostream>

using namespace std;

int main(){

    std::ostream output( std::cout.rdbuf());
    std::ostream error(std::cout.rdbuf());

    using Logger = std::pair< std::ostream, std::ostream >;
    Logger logger = std::make_pair( output, error );

  return 0;
}

But I get a compiler error that there isn't a matching constructor for pair<std::basic_ostream<char>, std::basic_ostream<char> >

jlconlin
  • 14,206
  • 22
  • 72
  • 105
  • FYI: in case you don't want a tuple-of-references (as some answers suggest) but a tuple-of-objects (as original question states) see [putting a non-copiable into a tuple](https://stackoverflow.com/a/32763826/717732) – quetzalcoatl Aug 13 '20 at 15:33
  • Depending on what you are trying to do, you might want to be aware of the [no-op output stream](https://stackoverflow.com/a/11826666/4641116). – Eljay Aug 13 '20 at 15:34
  • 1
    I was in inspired by your question to use ANSI escape sequences to make the `output` stream black text on white (class NormalBuffer : public std::streambuf), and the `error` stream white text on red (class RedBuffer : public std::streambuf). Useful for output to a terminal; not very useful redirecting to an output file. Thanks! – Eljay Aug 13 '20 at 17:51

2 Answers2

4

The problem that you’re having is that ostream can’t be copied.
The solution is to use a pair of references:

using Logger = std::pair<std::ostream &, std::ostream &>;
Logger logger { output, error };
Daniel
  • 30,896
  • 18
  • 85
  • 139
  • Of course. I didn't want to copy them anyway. I wanted a reference, but couldn't make it work. You've done however. – jlconlin Aug 13 '20 at 15:29
  • 1
    Dani - can't be copied doesn't mean it can't be put into a tuple. FYI: [putting a non-copiable into a tuple](https://stackoverflow.com/a/32763826/717732) - but yeah, I agree that keeping output/error obejcts elsewhere and passing references to output/error will probably make things easier. – quetzalcoatl Aug 13 '20 at 15:33
1

Instead of copying, which is not supported for streams, you can make pair of references to them

auto logger{::std::tie(output, error)};
user7860670
  • 35,849
  • 4
  • 58
  • 84