3

Using c++17

I have a header file colors.hpp to help me with colored output to stdout:

#pragma once
#include <string>

namespace Color
{
    static const std::string yellow = "\u001b[33m";
    static const std::string green = "\u001b[32m";
    static const std::string red = "\u001b[31m";
    static const std::string end = "\u001b[0m";
}

I often use it like this:

std::cout << Color::green << "some green text " << Color::end << std::endl;

I almost always put std::endl immediately after Color::end. I'd like to be able to achieve the same result (newline + buffer flush), but use only one variable - something like Color::endl.

I've only been able to come up with solutions that are string, which as far as I understand, will include the \n character but will not also force the flush to stdout.

static const std::string endl = std::ostringstream(static_cast<std::ostringstream &&>(std::ostringstream() << Color::end << std::endl)).str();

If I remove the .str() from the code above, then I can't do: std::cout << Color::endl; because of

error: invalid operands to binary expression ('basic_ostream<char>' and 'const std::__1::basic_ostringstream<char>')
vasia
  • 1,093
  • 7
  • 18
  • 1
    You might create a *"io-manipulator"*. – Jarod42 Sep 08 '21 at 14:49
  • What about some macro stuff? http://ix.io/3yhN – Ghasem Ramezani Sep 08 '21 at 14:50
  • 1
    You can reset the color and end the line automatically with this, if you're interested: https://godbolt.org/z/cMP9rjzvf – m88 Sep 08 '21 at 14:54
  • 1
    @GhasemRamezani I also sometimes use a few different colors per line, so the macros arent ideal for that case. I'm also trying to avoid macros because I'm trying to move away from the C99 style of writing C++ – vasia Sep 08 '21 at 14:58
  • 1
    @m88 thank you for providing that, it is a useful and instructive example! – vasia Sep 08 '21 at 15:01

1 Answers1

10

std::endl is a function (actually function template), not an object. That means, if you want to replicate it, you need a function as well.

If you add this to Color:

template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os )
{ 
    return os << end << std::endl;
}

Then, when you use this:

std::cout << Color::green << "some green text " << Color::endl;

The Color::endl() function will get called, and then it can insert Color::end into the stream, and then std::endl to get the newline and flush behavior you want, as seen in this live example.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
NathanOliver
  • 171,901
  • 28
  • 288
  • 402