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.
Related
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?
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.
I would like to iterate through a struct which is defined in other library whose source is not under my control. So any lib which requires to define the struct with its own macros/adaptors like previous questions is not usable here. I found the closest way is using boost::hana. However, it still requires to fill up an adaptor before I can iterate through it. I attached an example here. I wonder is there any way I can automate the BOOST_HANA_ADAPT_STRUCT then I do not need to fill up all the struct member names in there (those structs in total have more than hundred members).
#include <iostream>
#include <boost/hana.hpp>
#include <typeinfo>
namespace hana=boost::hana;
struct adapt_test
{
std::string name;
int data;
};
BOOST_HANA_ADAPT_STRUCT(
adapt_test
, name
, data
);
auto names = hana::transform(hana::accessors<adapt_test>(), hana::first);
int main() {
hana::for_each(
names,
[] (auto item)
{
std::cout << hana::to<char const *>(item) << std::endl;
}
);
adapt_test s1{"a", 2};
hana::for_each(
s1,
[] (auto pair)
{
std::cout << hana::to<char const *>(hana::first(pair)) << "=" << hana::second(pair) << std::endl;
}
);
return 0;
}
You can use Boost Flat Reflection like:
struct adapt_test
{
std::string name;
int data;
};
adapt_test s1{"a", 2};
std::cout << boost::pfr::get<0>(s1) << std::endl;
std::cout << boost::pfr::get<1>(s1) << std::endl;
boost::pfr::flat_for_each_field(s1, [] (const auto& field) { std::cout << field << std::endl; } );
P.S. Respect for #apolukhin for this library.
The basic answer to your question is no.
C++ does not treat identifiers as string literal (it could be indeed useful in some cases), and there is no bridge unfortunately between these kind of strings.
Hopefully, some standard one day will bring this ability, relieving us from having to go through macros or code generation, or maybe doing differently like this: telling "please treat my struct A { int x, y; } as a pair", where the meaning would be to match type of first and second to the members x and y and then building the types so that it works, it would be really useful for tuples as well. A kind of structured template matching.
Currently the best that can be done to my knowledge is to match structs to tuple without the names (as of C++17) because of the above limitation, such as with boost::hana or boost::fusion as you do.
So right now I'm trying to make a graphic C header file that could create shapes like triangle's, boxes, and circles in C++. Its supposed to help kids in my class, but I also want to be able for them to type stuff in the shapes. But I was wondering if there was a place holder for a integer in case you don't to cout<< a int.
For instance
the method (called up):
//goes to coordinates 5,6 (creates side of 5 with a char called 'X')
triangle(5,6,5,'X',"",5);
Will make a triangle with 2 sides of 5 units of X and have a regular base. But what if the user just wanted to print out the string w/o the integer. Then they would type
triangle(5,6,5,'X',"I love code", );
But an error would pop up and say that it needs one more parameter.
I've done some searching on boolean methods, like in java when you can type
public static void randommethod bool(/*params*\){
/*Enter code if its either true or false*/
}
But I've come up empty with any trying to find a method like that in C++.
Judging by the title you probably want to be able to pass either int or string which will be printed as message. You can template your triangle function to accept anything:
#include <iostream>
template <typename T>
void triangle(int x, int y, int z, char c, T anything)
{
std::cout << anything << std::endl;
}
int main()
{
triangle(5, 6, 5, 'X', "I love code");
triangle(5, 6, 5, 'X', 5);
return 0;
}
Will print:
I love code
5
As others have said, you can implement function overloading to achieve your desired behavior. Take a look at C++ Overloading to fully understand. Here is a brief example.
#include <iostream>
#include <string>
class Shapes
{
public:
void triangle(int x,
int y,
int z,
char unit,
std::string & text,
int optional)
{
std::cout << "triangle with optional parameters" << std::endl;
}
void triangle(int x,
int y,
int z,
char unit,
std::string & text)
{
std::cout << "triangle with minimal parameters" << std::endl;
}
};
I'm not really sure what each parameter corresponds to in your function, but if you want the last parameter to be optional, then you need to explicitly make it an optional parameter. When you create the function definition/prototype, you just assign the optional parameter the default value. If no value is provided, the default value is used.
For example, if I have a function to draw a triangle, I could write:
public void triangle(int base, int side1, int side2=1)
{
....
}
The side2 variable is optional. If no value is provided, 1 becomes the value. You could give the optional variable some kind of nonsense value that the function will detect and perform actions accordingly. Just make sure that the optional parameter is last in the list of parameters, otherwise it will give errors.
Hope this helps.
Ok so I'm confused about all this operator overloading stuff, the syntax is just weird to me and I'm not that great at programming anyway. So looking around on the internet apparently I think the only way for me to print out objects using cout << is to overload it. So I have a vector of objects and normally if I just had a regular vector of ints or strings then I'd just use an iterator and go through each one and then dereference it to print out whats in it, but I don't think that technique is working for the objects :-/ Here is what I have so far...help!
BarOne.h //my header file
#include <string>
#include <vector>
using namespace std;
class BarOne
{
private:
string name;
string type;
string size;
vector<BarOne> bar; //vector of BarOne objects
vector<BarOne>::iterator it; //iterator for bar
public:
BarOne(); //constructor
void addBottle(string, string, string); //adds a new bottle to bar
void revealSpace();
void printInventory();
friend ostream& operator<<(ostream& os, const BarOne& b);
};
and my implementation looks like:
BarOne.cpp //implementation
#include "BarOne.h"
#include <iostream>
#include <string>
using namespace std;
BarOne::BarOne()
{
//adding 4 default bottles
}
void BarOne::addBottle(string bottleName, string bottleType, string bottleSize)
{
name = bottleName;
type = bottleType;
size = bottleSize;
}
void BarOne::printInventory()
{
for (it = bar.begin(); it != bar.end(); ++it)
{
cout << *it << endl;
}
}
ostream& operator<<(ostream& os, const BarOne& b)
{
os << b.name << "\t\t\t" << b.type << "\t\t\t" << b.size;
return os;
}
so how come when i call printInventory in my main it doesn't do anything? Did I do the overloading wrong? Syntax mistakes?
ok this is the main too:
#include "BarOne.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
string Tiqo, Peruvian, Wellington, Smooze;
string vodka;
string rum;
string whiskey;
string small;
string medium;
string large;
//default bottles
vector<BarOne> bar; //vector of BarOne objects
vector<BarOne>::iterator it; //iterator for bar
BarOne Inventory; //BarOne object
Inventory.addBottle(Tiqo, vodka, large);
bar.push_back(Inventory);
Inventory.addBottle(Peruvian, rum, medium);
bar.push_back(Inventory);
Inventory.addBottle(Wellington, vodka, large);
bar.push_back(Inventory);
Inventory.addBottle(Smooze, whiskey, small);
bar.push_back(Inventory);
^^^thats just a piece of it...the rest is just formatting how things are displayed when the program runs and stuff. So ok I'll try and separate the classes like someone suggested tho. AddBottle adds the info for that object in the vector right? it gets the info and then adds it into the variables name, type and size and then its put into the vector "bar". Or no?
You don't show us your main() program. That code, together with your class design which confuses bar contents with the bar is causing the behavior you see.
The operator << is actually OK for outputting data of a bottle. But I'm sure that the BarOne on which it is called has an empty bar vector. Your addBottle() doesn't add anything anywhere (in particular not to the contained bar). Instead it simply sets the properties (data members) of the outer BarOne object.
The origin of that confusion is your class design, where a BarOne apparently is intended to serve both as bottle and as bar (which contains bottles).
I suggest you restart and try with separate Barand Bottleclasses.
BTW: Keeping the iterator you use in local loops as a class member is not a good idea. Sooner or later you will run into reentrancy problems with such approach. Loop iterators should be local variables, preferably scoped to the loop.