Operator Overloading Questions

Hello, this is my current code using operator overloads:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <string>

typedef unsigned int u32;
typedef unsigned char u8;

class ConsoleColor {
	std::string colorString;
public:
	ConsoleColor(u8 r, u8 g, u8 b) {
		this->colorString = "\x1b[38;2;" + std::to_string((u32) r) + ";" + std::to_string((u32) g) + ";" + std::to_string((u32) b) + "m";
	}

	static const ConsoleColor Red;
	static const ConsoleColor Green;
	static const ConsoleColor Blue;

	friend std::ostream& operator<<(std::ostream &ost, ConsoleColor const &color) {
		return ost << color.colorString;
	}

	friend std::string operator+(std::string const &str, ConsoleColor const &color) {
		return str + color.colorString;
	}

	friend std::string operator+(ConsoleColor const &color, std::string const &str) {
		return color.colorString + str;
	}
};

const ConsoleColor ConsoleColor::Red(255, 0, 0);
const ConsoleColor ConsoleColor::Green(0, 255, 0);
const ConsoleColor ConsoleColor::Blue(0, 0, 255);

int main(int argc, char **argv) {
	std::cout << ConsoleColor::Red << "This is red text.\x1b[0;0m" << std::endl; // RED > TEXT > RESET
	
	std::cout << (ConsoleColor::Red + "This is also red text.\x1b[0;0m") << std::endl; // RED > TEXT > RESET
	
	std::cout << ("This is white text." + ConsoleColor::Red) << std::endl; // NORMAL > TEXT > RED
	
	std::cout << "This is red text again.\x1b[0;0m" << std::endl; // RED > TEXT > RESET

	return 0;
}


Here are my questions:
* Are those two operator+ overloads created properly for the implied purpose of concatenating strings?
* Is using const& a good or bad idea in those places?
* Since the overloaded operators are non-static, should they reference this instead of color?


Sorry, I'm not very good at searching on google...
Last edited on
Are those two operator+ overloads created properly for the implied purpose of concatenating strings?
Looks ok.

Is using const& a good or bad idea in those places?
Using const is good. It's correct.

Since the overloaded operators are non-static, should they reference this instead of color?
Those operator overloads are not members of the class. They're external functions that have access to private parts of ConsoleColor (because they're friends). There is no this pointer.

This tweak of your program clarifies what's happening with those operator things.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <string>

typedef unsigned int u32;
typedef unsigned char u8;

class ConsoleColor {
	std::string colorString;
public:
	ConsoleColor(u8 r, u8 g, u8 b) {
		this->colorString = "\x1b[38;2;" + std::to_string((u32) r) + ";" + std::to_string((u32) g) + ";" + std::to_string((u32) b) + "m";
	}

	static const ConsoleColor Red;
	static const ConsoleColor Green;
	static const ConsoleColor Blue;

	friend std::ostream& operator<<(std::ostream &ost, ConsoleColor const &color);
	friend std::string operator+(std::string const &str, ConsoleColor const &color);
	friend std::string operator+(ConsoleColor const &color, std::string const &str);
};

std::ostream& operator<<(std::ostream &ost, ConsoleColor const &color) {
    return ost << color.colorString;
}

std::string operator+(std::string const &str, ConsoleColor const &color) {
    return str + color.colorString;
}

std::string operator+(ConsoleColor const &color, std::string const &str) {
    return color.colorString + str;
}

const ConsoleColor ConsoleColor::Red(255, 0, 0);
const ConsoleColor ConsoleColor::Green(0, 255, 0);
const ConsoleColor ConsoleColor::Blue(0, 0, 255);

int main(int argc, char **argv) {
	std::cout << ConsoleColor::Red << "This is red text.\x1b[0;0m" << std::endl; // RED > TEXT > RESET
	
	std::cout << (ConsoleColor::Red + "This is also red text.\x1b[0;0m") << std::endl; // RED > TEXT > RESET
	
	std::cout << ("This is white text." + ConsoleColor::Red) << std::endl; // NORMAL > TEXT > RED
	
	std::cout << "This is red text again.\x1b[0;0m" << std::endl; // RED > TEXT > RESET

	return 0;
}
Last edited on
Thanks for replying! And thanks for clearing up what friend does. I just copied the idea from some code that someone gave me one, I had no idea what it meant because I read an outdated book. Thanks a lot! :D
There's a funny thing still, aside from what kbw mentioned. One important aspect of programming is the notion of the "interface" of the functionality, and its separation from the actual implementation of the functionality.

The goal here is that you want the user to be able to use your ConsoleColor class to easily produce colored text. Sure, that's good. The issue is that with lines like "\x1b[0;0m" you're forcing the user to still know how to implement ConsoleColor themselves (i.e. they have to know that it's some specific set of magic strings they need to invoke for console to stop being a particular color).

One easy way to do this would be to just have a "ConsoleColor::Reset" static variable that the user also invokes, so they needn't worry about what "\x1b[0;0m" means.
e.g. cout << ConsoleColor::Red << "This is red " << ConsoleColor::Reset << "This is normal\n";

Another way to do this would for a ConsoleColor to always handle resetting the console itself. This is a less straight-forward path, but might be better depending on the intended use-case.

For example, you could have something like:
1
2
3
4
5
ConsoleColor(std::cout, ConsoleColor::Red) << "This is red text";
// or maybe
ConsoleColor(std::cout) << ConsoleColor::Red << "This is red text";

std::cout << "This is normal text.";

where the destruction of the ConsoleColor object automatically resets the color state of the stream by sending "\x1b[0;0m" to it.
What I showed might still be a bit clunky, but it's just to get the idea across of possible alternatives.
Last edited on
[bold]@Ganado[/bold] Thanks! That is a problem. I will do my best to watch for such carelessness on my own part. Thank you for pointing that out and your suggested alternatives, I will consider using them in the future.
Topic archived. No new replies allowed.