4

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

Bulat
  • 720
  • 7
  • 15
play store
  • 393
  • 1
  • 5
  • `std::ostream& operator<<(std::ostream& o, color c) { o << (o == red ? "red" : o == blue ? "blue" : o == black ? "black" : "hazy"); return o; }` – Eljay Jun 06 '19 at 04:34

3 Answers3

2

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';
}
john
  • 85,011
  • 4
  • 57
  • 81
1

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.

Henry
  • 54
  • 7
1

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.

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59