1

I want to write a program and enable the user to have control over the logging of the package by setting the program to display progress or disable that.

I know that std::cout is an std::ostream with the difference that std::cout redirects the results to standard output.

I want my class to have an std::ostream member that I log everything to. Then if the user enables display, that member will be attached to std::cout and displays the results, otherwise it wont.

What I have in mind is something similar to this:

class log {
private:
    std::ostream display;
public:
    void func();
    void show_display();
}

void log::func(){
    display << "called by func";
}
void log::show_display(){
    // redirect display to standard output
}

Is there any way similar to above to do this? If not, how can I have similar results?

Thanks.

Everyone
  • 1,751
  • 13
  • 36
  • 3
    "with the difference that std::cout puts the results to the screen directly." - no, it writes to standard output - you can redirect that from your shell. –  May 07 '17 at 22:07
  • @NeilButterworth That's absolutely correct, I am sorry for the mistake. I will edit – Everyone May 07 '17 at 22:08
  • You can use this for the stream that ignores the output: http://stackoverflow.com/a/11826666/951890 – Vaughn Cato May 07 '17 at 22:09
  • @VaughnCato Thanks for the suggestion, i was hoping for something that i have control over to redirect the stream to the standard output whenever i wish to do so. – Everyone May 07 '17 at 22:19
  • You can have `display()` be a function that returns a `std::ostream&`, which is either a no-op stream, or `std::cout` based on whether logging is enabled or not. – Vaughn Cato May 07 '17 at 22:25

1 Answers1

3

Stream handles aren't copyable objects, nor are there any std::ostream objects that you the user can instantiate. So your class as written cannot work. What you could do instead is store a pointer:

#include <iostream>

class log {
  std::ostream* out_;

public:
  void func() {
    if (out) { *out << "called by func"; }
    // ...
  }

  void show_display() {
    out = &std::cout;
  }

  void hide_display() {
    out = nullptr;
  }
};

If you plan to build a more general-purpose logging system, you should consider whether logging to a disabled output requires evaluation of operands; users may expect that a log statement such as log << expensive_function(); is cheap when the logging is disabled.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • I gotta admit i had this in mind but was hoping for another way that does not involve checking if it isnt a `nullptr` each time i wanted to log. I might as well end up just writing a function `write` that does the checking and puts it in the stream. – Everyone May 07 '17 at 22:13
  • @Everyone: You could also create your own logger object that doesn't write anything and unconditionally log to that and plug that in instead of the null pointer. – Kerrek SB May 07 '17 at 22:15
  • I think i will end up doing just that because i would have control over the thread safety issues that come up with `std::cout` – Everyone May 07 '17 at 22:17