I wanted to create a method to add color to console output that would work in a similar way to std::left and std::setw(). I ended up with the code below, and it works exactly how I want it to. I understand how it works, but I would some clarification on something.
Here is the code:
#include <iostream>
#include <Windows.h>
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
enum class color { blue = FOREGROUND_BLUE, green, cyan, red, purple, yellow, white, bright = FOREGROUND_INTENSITY };
class coutColor {
public:
WORD Color;
coutColor(color colorvalue) : Color((WORD)colorvalue) { }
~coutColor() { SetConsoleTextAttribute(hConsole, (WORD)7); }
};
std::ostream& operator<<(std::ostream& os, const coutColor& colorout) {
SetConsoleTextAttribute(hConsole, colorout.Color);
return os;
}
int main() {
std::cout << coutColor(color::green) << "This text is green!\n";
std::cout << color::red << "This text is red! " << 31 << "\n";
return 0;
}
I understand how coutColor(color::green) works in the cout in main(), but why does just color::red by itself work as well?
I stumbled upon it by accident while testing different things.
How can it take the enum type color as an input, since it's not in the input parameters of the overloaded operator<<?
Why does it do the same thing as inputting coutColor(color::red)?
why does just color::red by itself work as well? ... How can it take the enum type color as an input, since it's not in the input parameters of the overloaded operator<<? Why does it do the same thing as inputting coutColor(color::red)?
It is because coutColor's constructor is not marked as explicit.
When the compiler is looking for a suitable overload of operator<< for the expression std::cout << color::red, it finds your overload in scope and sees that:
coutColor is implicitly constructable from a color value
the operator takes a coutColor object by const reference
So, the compiler is able to create a temporary coutColor object, passing the color value to its constructor, and then pass that object to the operator.
I have seen function(input) : var(input) {} before and I didn't know what it meant.
C++, What does the colon after a constructor mean?
Related
I know that enum inheritance is not possible in c++, but I am looking for specific data structure that simply fit into my case. Suppose I have these two enums:
enum Fruit { apple, orange};
enum Drink { water, milk};
I want a parent for these two that I can use as parameter in this abstract method
void LetsEat(Eatable eatable){}
They are going to be used as simple switches, and basically I want to keep my code clean and type safe. I wonder if I will be forced to use inherited classes that needs to be initialized. It is too much for this simple problem.
Speaking very generally, enums are just dressed up ints.
enum Fruit { apple, orange};
If you look at the compiled code, you will discover that an apple will be represented by the value 0, and an orange will be represented by the value 1.
enum Drink { water, milk};
Same thing here will happen here. water will be represented by value 0, and milk will be represented by value 1. You can begin to see the obvious problem here.
One, a slightly primitive, solution is equivalent to letting a bull loose in the china shop:
enum Drink { water=2, milk=3};
Now you could cook something up where you're passing in a int value and figure out what exactly was passed in, by its value.
But this will likely require plenty of ugly casts, everywhere. The resulting code, if posted to Stackoverflow, will likely to attract downvotes.
The downvotes will be because there are cleaner solutions that are available in modern, post C++17 world. For starters, you can switch to enum classes.
enum class Fruit { apple, orange};
enum class Drink { water, milk};
This gains additional type-safety. It's not as easy, any more, to assign a Fruit to a Drink. Your C++ compiler will bark, very loudly, in many situations where it would raise a warning. Your C++ compiler will help you find even more bugs, in your code. It is true that this will require a little bit more typing. You will always have to specify enumerated values everywhere with full qualification, i.e. Fruit::apple and Drink::water, when in your existing code a mere apple and water will suffice. But a few extra typed characters is a small price to pay for more type-safe code, and for being able to simply declare:
typedef std::variant<Fruit, Drink> Eatable;
and simply do what you always wanted:
void LetsEat(Eatable eatable){}
and everything will work exactly how you wanted it. LetsEat will accept either a Fruit or a Drink as its parameter. It will have to do a little bit more work, to figure out what's in the std::variant, but nobody ever claimed that C++ is easy.
std::variant is one of the more complex templates in the C++ library, and it's not possible to explain how to use it, fully, in a short paragraph or two on Stackoverflow. But this is what's possible, and I'll refer you to your C++ textbook for a complete description of how to use this template.
This sounds like an excellent use case for std::variant.
#include <variant>
#include <iostream>
// Define our enums
enum Fruit { Apple, Orange };
enum Drink { Water, Milk };
// An Eatable is either a Fruit or a Drink
using Eatable = std::variant<Fruit, Drink>;
void letsEat(Eatable eatable) {
// We can use the index() method to figure out which one we have
switch (eatable.index()) {
case 0:
std::cout << "It's a Fruit!" << std::endl;
break;
case 1:
std::cout << "It's a Drink!" << std::endl;
break;
}
}
int main() {
letsEat(Apple);
letsEat(Water);
}
Note that std::variant<Fruit, Drink> is not, strictly speaking, a supertype of Fruit or Drink. Instead, it's a new type altogether but we get implicit conversions from Fruit and Drink to std::variant<Fruit, Drink> via its constructors.
If you're not using C++17, you can use boost::variant from the Boost C++ libraries.
You can use std::variant<T, ...> if you use C++17 or above:
#include <iostream>
#include <variant>
#include <type_traits>
enum Fruit { apple, orange };
enum Drink { water, milk };
using Eatable = std::variant<Fruit, Drink>;
void LetsEat(Eatable const eatable) {
std::visit([] (auto&& v) {
using T = std::decay_t<decltype(v)>;
if constexpr (std::is_same_v<T, Fruit>) {
// Now use it like you would use a normal 'Fruit' variable ...
}
if constexpr (std::is_same_v<T, Drink>) {
// Now use it like you would use a normal 'Drink' variable ...
}
}, eatable);
}
int main() {
LetsEat(apple);
}
Alternatively, you could just create a class that is implicitly convertible to either enum type:
class Eatable {
union {
Fruit f;
Drink d;
} u_;
bool has_fruit_;
public:
Eatable(Fruit f) : has_fruit_(true) {
u_.f = f;
};
Eatable(Drink d) : has_fruit_(false) {
u_.d = d;
};
operator Fruit() const {
return u_.f;
}
operator Drink() const {
return u_.d;
}
bool has_fruit() const {
return has_fruit_;
}
};
Then you can use it like this:
void LetsEat(Eatable const eatable) {
if (eatable.has_fruit()) {
Fruit const f = eatable;
switch (f) {
case apple:
std::cout << "Fruit: apple" << std::endl;
break;
case orange:
std::cout << "Fruit: orange" << std::endl;
break;
default: break;
}
} else {
Drink const d = eatable;
switch (d) {
case water:
std::cout << "Drink: water" << std::endl;
break;
case milk:
std::cout << "Drink: milk" << std::endl;
break;
default: break;
}
}
}
I am wondering if it is possible to initialize an enum class as null. I have written up a short example to illustrate what I am asking about.
I have a header here that defines an enum class called ColorOptions
#ifndef COLORS_HPP
#define COLORS_HPP
enum class ColorOptions
{
RED,
BLUE
};
#endif
and I also have a class that is using this enum class to print colors based on the enum value
#include "Colors.hpp"
#include <iostream>
void printColor(ColorOptions col);
int main()
{
printColor(ColorOptions::RED);
printColor(ColorOptions::BLUE);
}
void printColor(ColorOptions col)
{
switch(col)
{
case ColorOptions::RED:
std::cout << "The color is red" << std::endl;
break;
case ColorOptions::BLUE:
std::cout << "The color is blue" << std::endl;
break;
default:
std::cout << "The color is unknown" << std::endl;
}
}
Is it possible to initalize a ColorOptions as something other than RED or BLUE in this case? I want to reach the default case of the printColor method, but I am not sure if it is possible without adding another type to the ColorOptions enum.
The way to get a value not of the valid enumerations is to use static_cast. That would look like
printColor(static_cast<ColorOptions>(5));
and that will output
The color is unknown
If you can use C++17 then a nice thing you can do would be to change the enum to something like
enum class ColorOptions
{
NONE,
RED,
BLUE
};
and then you can call your function like
printColor({});
which will give you an implicit value of NONE and cause The color is unknown to be print.
This question already has answers here:
enum to string in modern C++11 / C++14 / C++17 and future C++20
(32 answers)
C++: Print out enum value as text
(13 answers)
Closed 3 years ago.
I created an enum names color. And then made a variable background_color of type color. Then assign a enum value, suppose blue. Then I wanted to print background_color using cout. But It prints the corresponding int value of enum member. I wanted to know if there any manipulator which will print the background_color as a string. I know I could use switch cases to get so. But I wished I could acquire this using cout and manipulator.
#include <iostream>
using namespace std;
int main()
{
enum color
{
red,blue,black
};
color background_color=blue;
cout << background_color;
return 0;
}
I expected to print blue as output not 1.A
No there isn't, but you could use a std::map to hold your colors and their names.
#include <iostream>
#include <map>
#include <string>
enum color { red, blue, black };
std::map<color, std::string> color_names{ { red, "red"}, { blue, "blue"}, { black, "black"} };
int main()
{
std::cout << "my favorite color is " << color_names[red] << '\n';
}
You can create a macro that does this.
#define ENUM_TO_STRING(var) (#var)
Then, when you want to use it,
enum Test
{
Test_A,
Test_B
}
int main()
{
std::cout << ENUM_TO_STRING(Test_A) << std::endl;
return 1;
}
This doesn't work for enum stored in a variable though.
I wanted to know if there any manipulator which will print the background_color as a string .
A simple answer: to the best of my knowledge there is no manipulator that will do this for you directly. However, there are plenty of tools and methods to achieve what you want. One had already suggested using an std::map. That is one valid possible way and there are many others each having their own pros and cons. It is up to you to balance out the differences.
Instead of using std::map I chose to use a static const std::array. I also decided to place the enum inside of a struct that contains a constructor and two variables. The type it is and a string for its name. Then I created an overloaded operator<<() to work on my struct for its output.
Here is what my code looks like:
Test.h
#include <array>
#inlucde <iostream>
#include <string>
// must match the size and order of
// the enumeration in the Color Struct
static const std::array<std::string, 8> name {
"Black",
"Red",
"Orange",
"Yellow",
"Green",
"Blue",
"White",
"Invalid"
};
struct Color {
enum Type {
BLACK,
RED,
ORANGE,
YELLOW,
GREEN,
BLUE,
WHITE,
INVALID,
} type_;
std::string name_;
explicit Color(Color::Type ty = INVALID) : type_(ty), name_(name[ty] ) {}
};
std::ostream& operator<<(std::ostream& os, const Color& color );
Test.cpp
#include "Test.h"
std::ostream& operator<<(std::ostream& os, const Color& color) {
return os << color.name_;
}
main.cpp
#include "Test.h"
int main() {
Color blank;
Color red(Color::RED);
Color white(Color::WHITE);
Color blue(Color::BLUE);
std::cout << blank << " "
<< red << " "
<< white << " "
<< blue << '\n';
return EXIT_SUCCESS;
}
Output
Invalid Red White Blue
I choose array over map for it has faster access time. Also I chose to make it a const static so that it would only have to be initialized once! These are the pros of my method.
The con is that the array is const and can not be modified, and you can not insert into an array. However because we are dealing with an enumeration, this shouldn't be an issue because you can not add to an enum after its been declared for it is an integral type and not a container.
Another pro to this method is that you do not have to worry about using a switch statement. The only con here is the storage space of two variables, an enum type and a string, but this should not create a large impact for a memory footprint unless if you are storing millions or billions of colors.
The design structure above is good for when you have a limited or a specified amount of objects that you know your application is going to support. Even if you declared 100 predefined colors, this approach is still manageable.
On the other hand if you are storing thousands or tens of thousands of different colors then an std::map might make more sense. In that case, you could declare a static map<unsigned, string> and move it inside of the class, then have a static function that will initialize the map with all of the string names for each of the different object types you will support.
A problem occurred when trying to print out a class method which has en enum class type.
I have a method, which returns an enum which is casted to bool:
bool Window::IsVSync() const
{
return static_cast<bool>(m_WindowData.VSync);
}
m_WindowData.VSync is VSync type.
And that's the enum class:
enum class VSync : bool
{
Disable = false,
Enable = true
}
I know that with enum class I don't get an implicit conversion, and that's the reason I cast to bool. And like that everything is working just fine. But with the fact that my enum class is extended from bool in mind, can I do something like this:
VSync Window::IsVSync() const
{
return m_WindowData.VSync;
}
At first, I thought I could, since we extend the enum class from bool, but I was wrong, and It gives me this error when I try to print to the console:
binary '<<': no operator found which takes a right-hand operand of
type 'VSync' (or there is no acceptable conversion)
I print the method to the console with:
std::cout << myWindow.IsVSync() << "\n";
Which is of course, supposed to return either 1 or 0;
When I cast it to bool in the output like that:
std::cout << static_cast<bool>(myWindow.IsVSync()) << "\n";
it works just fine, but I do not want to make the user have to cast it to bool for it to work. I need a solution which is in the method itself, so the calling stays like that
std::cout << myWindow.IsVSync() << "\n";
You can define a stream operator overload outside of the class for the enum type like so:
static std::ostream& operator<<(std::ostream& os, const VSync& val)
{
switch (val) {
case VSync::Disable:
os << "VSync disabled";
break;
case VSync::Enable:
os << "VSync enabled";
break;
}
return os;
}
In this way you don't need to cast anything and can print something more detailed than a 1 or 0 (or having to use std::boolalpha).
I hope that can help.
It is not extended from bool, is uses the same amount of space as a bool.
With enum, colon does not denote inheritance.
I've always been taught that
1. Class c(arg);
and
2. Class c = arg;
are two totally equivalent statements, but look at this situation.
#include <iostream>
class Intermediary {
};
class Left {
public:
Left(const Intermediary &) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
class Right {
public:
// The argument is there just so that the example can work, see below
Right(int) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
operator Intermediary () const {
std::cout << __PRETTY_FUNCTION__ << std::endl;
return Intermediary();
}
};
Now if I do this:
Left l = Right(0);
The compiler will complain
error: conversion from Right to non-scalar type Left requested
But if I do this:
Left l(Right(0));
Then everything compiles and the output is
Right::Right(int)
Right::operator Intermediary() const
Left::Left(const Intermediary&)
However, if I do this:
Left l = (Intermediary)Right(0);
then everything compiles again and the output is just like the one above.
So obviously
1. Class c(arg);
and
2. Class c = arg;
are not the same, but why not, and what's the difference? I couldn't find anything about this online.
I've always been taught that Class c(arg); and Class c = arg; are two totally equivalent statements, but look at this situation.
It turns out they are not equivalent. The first one constructs the Class c out of an arg, while the second one constructs a Class out of an arg and then copy-constructs Class c out of it. Note that the implementation is allowed to ellide that copy, and it usually does.
Left l = Right(0);
This requires a conversion from Right to Intermediary, and one from Intermediary to Left. This two sequential user defined conversions are not allowed by the standard, you have to do at least one of them explicit as you do with:
Left l = (Intermediary)Right(0);