I had this question on a test.
I know that I can do something like:
enum class Color { red, green = 1, blue };
Color c = Color::blue;
if( c == Color::blue )
cout << "blue\n";
But when I replace cout << "blue\n"; with cout << Color::green, it doesn't even compile. Why doesn't it compile?
This error happens because C++ does not have a pre-defined way of printing an enum. You need to define an operator << for printing objects of Color enum type according to your needs.
For example, if you would like to print the numeric value, cast the color to int inside your operator:
ostream& operator<<(ostream& ostr, const Color& c) {
ostr << (int)c;
return ostr;
}
Demo.
If you would like to print enum value as text, see this Q&A for a sample implementation.
Related
Problem:
I have a structure that represent RGB colors. I would like to define an enum to be able to directly assign the colors to a variable.
1) Desired enum of struct:
What I would like is to define an enum that directly maps a color name to its value, just like I would do with an integer parameter or a list of items.
#include <iostream>
#include <array>
typedef struct _Color_3u8
{
std::array<unsigned char,3> rgb;
} Color_3u8;
std::ostream& operator<<(std::ostream& os, const Color_3u8& dt)
{
os << "R: " << (int)dt.rgb[0] << " | G: " << (int)dt.rgb[1] << " | B: " << (int)dt.rgb[2] << "\n";
return os;
}
typedef enum _Default_color
{
RED = (Color_3u8){255,0,0},
GREEN = (Color_3u8){0,255,0},
BLUE = (Color_3u8){0,0,255},
} Default_color;
int main()
{
Color_3u8 my_color = Default_color::RED;
std::cout << my_color;
return 0;
}
Now, the code above clearly doesn't work because enums are limited to integers.
2) constant array + enum:
One way to make it work is to use a constant array filled with the vaules and use the enum to index that array. It looks a lot clunkier since there are two separate definitions.
#include <iostream>
#include <array>
typedef struct _Color_3u8
{
std::array<unsigned char,3> rgb;
} Color_3u8;
std::ostream& operator<<(std::ostream& os, const Color_3u8& dt)
{
os << "R: " << (int)dt.rgb[0] << " | G: " << (int)dt.rgb[1] << " | B: " << (int)dt.rgb[2] << "\n";
return os;
}
typedef enum _Default_color
{
RED = 0,
GREEN = 1,
BLUE = 2,
NUM_COLORS = 3,
} Default_color;
const std::array<Color_3u8,Default_color::NUM_COLORS> c_default_colors=
{
(Color_3u8){255,0,0},
(Color_3u8){0,255,0},
(Color_3u8){0,0,255},
};
int main()
{
Color_3u8 my_color = c_default_colors[Default_color::BLUE];
std::cout << my_color;
return 0;
}
Output: "R: 0 | G: 0 | B: 255"
3) struct class:
Another way I can think of is to move the constant array from code 2) inside the structure and add a method to initialize the structure to a default color. It would work and it would be very clean, but like the 2), it would be more effort to add a color than I feels is necessary... I feel there should be a way to make code 1) work in some form.
4) Hack struct into integer
In this case since my structure is three bytes, I can convert a color to its integer representation and use that for the enum. I would like to find a way that works with structures bigger than an int as well.
Solution) namespace+constexpr
constexpr is used to declare a compile time variable ofthe right type with the right constructor. namespace wraps around the definitions and scope them.
struct Color_3u8
{
std::array<unsigned char,3> rgb;
};
std::ostream& operator<<(std::ostream& os, const Color_3u8& dt)
{
os << "R: " << (int)dt.rgb[0] << " | G: " << (int)dt.rgb[1] << " | B: " << (int)dt.rgb[2] << "\n";
return os;
}
namespace Default_color
{
constexpr Color_3u8 RED{255,0,0};
constexpr Color_3u8 GREEN{0,255,0};
constexpr Color_3u8 BLUE{0,0,255};
};
int main()
{
Color_3u8 my_color = Default_color::RED;
std::cout << my_color;
return 0;
}
Question
Is there a way in C++ to make something similar to code 1)? I would like to map a name to a structure content with just one entry in one table, like the enum does.
I would use inline constexpr variables and wrap them in a namespace. That would look like
namespace Default_colors
{
inline constexpr Color_3u8 RED{255,0,0};
inline constexpr Color_3u8 GREEN{0,255,0};
inline constexpr Color_3u8 BLUE{0,0,255};
}
and then you would use it like
Default_colors::RED
The reason to use inline variables here is so you can declare them in a header file and not have to worry about defining them in a single translation unit.
Also note that in C++, there is no reason to do
typedef struct _Color_3u8
{
std::array<unsigned char,3> rgb;
} Color_3u8;
like you have to do in C. In C++, you can just use
struct Color_3u8
{
std::array<unsigned char,3> rgb;
};
What if I told you that you can store information about all the three colors in a single variable? Will you believe me? Well this is how,
If you know about binary, if we OR something, it adds the '1' bit to a certain location (in binary). This means that we can assign a binary value to each color, and by OR-ing it, we can store the data about the color.
#define BIT_SHIFT(x) (1 << x)
enum Colors {
Red = BIR_SHIFT(0), // Which is gonna be 1.
Green = BIR_SHIFT(1), // Which is gonna be 2.
Blue = BIR_SHIFT(2), // Which is gonna be 4.
};
Now we can have a variable to store the colors,
int colors = Colors::Red | Colors::Green;
Now when were gonna print, we just need to AND the color to check if its there.
std::ostream& operator<<(std::ostream& os, const Color_3u8& dt)
{
// Red color value.
if(colors & Colors::Red)
os << "R: 255 |";
else
os << "R: 0 |"
// Green color value.
if(colors & Colors::Green)
os << "G: 255 |";
else
os << "G: 0 |"
// Blue color value.
if(colors & Colors::Blue)
os << "B: 255\n";
else
os << "B: 0\n"
return os;
}
One downside of using this is that you cant store the individual color values (meaning its gonna be either 0 or 255, which I came to conclusion using the example). But on the plus size, you only need one variable to get it done.
In c++, Is there any format specifier to print an unsigned in different base, depending on its value? A format specifier expressing something like this:
using namespace std;
if(x > 0xF000)
cout << hex << "0x" << x;
else
cout << dec << x ;
Because I will have to do this a lot of times in my current project, I would like to know if c++ provides such a format specifier.
There is no such functionality built-in to C++. You can use a simple wrapper to accomplish this, though:
struct large_hex {
unsigned int x;
};
ostream& operator <<(ostream& os, const large_hex& lh) {
if (lh.x > 0xF000) {
return os << "0x" << hex << lh.x << dec;
} else {
return os << lh.x;
}
}
Use as cout << large_hex{x}.
If you want to make the threshold configurable you could make it a second field of large_hex or a template parameter (exercise for the reader).
I alredy parsed file and split content to enum or enum classes.
std::string sourceString = readFromFile(typesHDestination);
boost::smatch xResults;
std::string::const_iterator Start = sourceString.cbegin();
std::string::const_iterator End = sourceString.cend();
while (boost::regex_search(Start, End, xResults, boost::regex("(?<data_type>enum|enum\\s+class)\\s+(?<enum_name>\\w+)\\s*\{(?<content>[^\}]+?)\\s*\}\\s*")))
{
std::cout << xResults["data_type"]
<< " " << xResults["enum_name"] << "\n{\n";
std::string::const_iterator ContentStart = xResults["content"].begin();
std::string::const_iterator ContentEnd = xResults["content"].end();
boost::smatch xResultsInner;
while (boost::regex_search(ContentStart, ContentEnd, xResultsInner, boost::regex("(?<name>\\w+)(?:(?:\\s*=\\s*(?<value>[^\,\\s]+)(?:(?:,)|(?:\\s*)))|(?:(?:\\s*)|(?:,)))")))
{
std::cout << xResultsInner["name"] << ": " << xResultsInner["value"] << std::endl;
ContentStart = xResultsInner[0].second;
}
Start = xResults[0].second;
std::cout << "}\n";
}
Its ok if enums are without comments.
I tried to add named group <comment> to save comments in enums, but failed every time. (\/{2}\s*.+) - sample for comments with double slashes.
I tested using this online regex and with boost::regex.
The first step - from *.cpp file to <data_type> <enum_name> <content>
regex:
(?'data_type'enum|enum\s+class)\s+(?'enum_name'\w+)\s*{\s*(?'content'[^}]+?)\s*}\s*
From <content> to <name> <value> <comment>
regex:
(?'name'\w+)(?:(?:\s*=\s*(?'value'[^\,\s/]+)(?:(?:,)|(?:\s*)))|(?:(?:\s*)|(?:,)))
The last one contains error. Is there any way to fix it and add feature to store coments in group?
As some comments said, may it is not a good idea to parse a source file with Regular Expression except with some simple cases
for example this source file, from: http://en.cppreference.com/w/cpp/language/enum
#include <iostream>
// enum that takes 16 bits
enum smallenum: int16_t
{
a,
b,
c
};
// color may be red (value 0), yellow (value 1), green (value 20), or blue (value 21)
enum color
{
red,
yellow,
green = 20,
blue
};
// altitude may be altitude::high or altitude::low
enum class altitude: char
{
high='h',
low='l', // C++11 allows the extra comma
};
// the constant d is 0, the constant e is 1, the constant f is 3
enum
{
d,
e,
f = e + 2
};
//enumeration types (both scoped and unscoped) can have overloaded operators
std::ostream& operator<<(std::ostream& os, color c)
{
switch(c)
{
case red : os << "red"; break;
case yellow: os << "yellow"; break;
case green : os << "green"; break;
case blue : os << "blue"; break;
default : os.setstate(std::ios_base::failbit);
}
return os;
}
std::ostream& operator<<(std::ostream& os, altitude al)
{
return os << static_cast<char>(al);
}
int main()
{
color col = red;
altitude a;
a = altitude::low;
std::cout << "col = " << col << '\n'
<< "a = " << a << '\n'
<< "f = " << f << '\n';
}
the key pattern here is: starting with enum and end with ; and you cannot predict any text between enum and ; there will be so many possibilities! and for that you can use .*? lazy star
Thus if I want to extract all enums I use:
NOTE: it is not the efficient way
boost::regex rx( "^\\s*(enum.*?;)" );
boost::match_results< std::string::const_iterator > mr; // or boost::smatch
std::ifstream ifs( "file.cpp" );
const uintmax_t file_size = ifs.seekg( 0, std::ios_base::end ).tellg();
ifs.seekg( 0, std::ios_base::beg ); // rewind
std::string whole_file( file_size, ' ' );
ifs.read( &*whole_file.begin(), file_size );
ifs.close();
while( boost::regex_search( whole_file, mr, rx ) ){
std::cout << mr.str( 1 ) << '\n';
whole_file = mr.suffix().str();
}
which the output will be:
enum smallenum: int16_t
{
a,
b,
c
};
enum color
{
red,
yellow,
green = 20,
blue
};
enum class altitude: char
{
high='h',
low='l', // C++11 allows the extra comma
};
enum
{
d,
e,
f = e + 2
};
And Of course for such simple thing I prefer to use:
perl -lne '$/=unlef;print $1 while/^\s*(enum.*?;)/smg' file.cpp
that has the same output.
And may this pattern helps you if you want to match each section separately
^\s*(enum[^{]*)\s*({)\s*([^}]+)\s*(};)
But again this is not a good idea except for some simple source files. Since C++ Source Code has free style and not all code writers follow the standard rules. For example with the pattern above, I assumed that (};) the } comes with ; and if someone separates them ( which is still a valid code ) the pattern will be failed to match.
I argree with the fact that using regex to parse complicated data is not the best solution. I'v made an omission of the few major conditions. First of all, i parsed some kind of generated source code containing emuns and enum classes. So there were no suprises in code, and code was regular. So i parsing regular code with regex.
The Answer:
(the first step is the same, the second was fixed)
How to parse enums/emun classes with regex:
The first step - from *.cpp file to <data_type> <enum_name> <content> regex:
(?'data_type'enum|enum\s+class)\s+(?'enum_name'\w+)\s*{\s*(?'content'[^}]+?)\s*}\s*
From <content> to <name> <value> <comment> regex:
^\s*(?'name'\w+)(?:(?:\s*=\s*(?'value'[^,\n/]+))|(?:[^,\s/]))(?:(?:\s$)|(?:\s*,\s*$)|(?:[^/]/{2}\s(?'comment'.*$)))
All test were ok and here is marked text by colors.
Let's say Ì have some class and added output functionality by overloading the left-shift operator:
struct Foo
{
int i = 1;
std::string s = "hello";
};
auto& operator<<(std::ostream& os, Foo const& foo)
{
os<<foo.i<<"\n";
os<<foo.s<<"\n";
return os;
}
What is a good way to indent the output?
Example: If I write
std::cout<<" "<<Foo{}<<std::endl;
the output is:
1
hello
Obviously, hello is not indented. Is there an easy way to indent the whole output (and not just the first element)?
You're serializing the Foo object right? So logically the serialized string of Foo is an implementation detail of Foo. You could write your own stream class or something along those lines but that is overengineering the problem.
auto& operator<<(std::ostream& os, Foo const& foo)
{
auto s = "\t" + std::to_string(foo.i) + "\n"
"\t" + foo.s;
return (os << s);
}
int main()
{
std::cout << Foo{} << "\n";
}
You can use the standard library manipulator setw to set the width of a field, which often results in indenting the text. Here's how you use it:
cout << std::setw(10) << "Viola!" << std::endl;
This will print the word "Viola!" indented by 4 spaces. Why 4 spaces? The parameter to setw() determines the entire width of the "field", which includes the 6 characters in "Viola!".
By default, setw() will align the text to the right, but can be made to align left by using another manipulator left. Here's an example:
cout << std::setw(10) << std::left << "Viola!" << std::endl;
This will output the string "Viola!" with no indentation, but with 4 spaces after it.
That should answer your original question about a good way to indent, and setw() is not just a good way, but the standard way.
The second question asks about how to have persistent indentation, and the answer is that there is not an easy way. The easiest approach is to add the call to setw() (or whichever indentation method that you use) in each of the calls to cout.
In addition to those answers, you should consider replacing the use of "\n" in your calls to cout with a call to endl. endl is the "end of line" manipulator, and makes your code work properly with any output stream. The code would look like this:
auto& operator<<(std::ostream& os, Foo const& foo)
{
os << foo.i << std::endl;
os << foo.s << std::endl;
return os;
}
I can make an std::ostream object output integer numbers in hex, for example
std::cout << std::hex << 0xabc; //prints `abc`, not the base-10 representation
Is there any manipulator that is universal for all bases? Something like
std::cout << std::base(4) << 20; //I want this to output 110
If there is one, then I have no further question.
If there isn't one, then can I write one? Won't it require me to access private implementation details of std::ostream?
Note that I know I can write a function that takes a number and converts it to a string which is the representation of that number in any base. Or I can use one that already exists. I am asking about custom stream manipulators - are they possible?
You can do something like the following. I have commented the code to explain what each part is doing, but essentially its this:
Create a "manipulator" struct which stores some data in the stream using xalloc and iword.
Create a custom num_put facet which looks for your manipulator and applies the manipulation.
Here is the code...
Edit: Note that im not sure I handled the std::ios_base::internal flag correctly here - as I dont actually know what its for.
Edit 2: I found out what std::ios_base::internal is for, and updated the code to handle it.
Edit 3: Added a call to std::locacle::global to show how to make all the standard stream classes support the new stream manipulator by default, rather than having to imbue them.
#include <algorithm>
#include <cassert>
#include <climits>
#include <iomanip>
#include <iostream>
#include <locale>
namespace StreamManip {
// Define a base manipulator type, its what the built in stream manipulators
// do when they take parameters, only they return an opaque type.
struct BaseManip
{
int mBase;
BaseManip(int base) : mBase(base)
{
assert(base >= 2);
assert(base <= 36);
}
static int getIWord()
{
// call xalloc once to get an index at which we can store data for this
// manipulator.
static int iw = std::ios_base::xalloc();
return iw;
}
void apply(std::ostream& os) const
{
// store the base value in the manipulator.
os.iword(getIWord()) = mBase;
}
};
// We need this so we can apply our custom stream manipulator to the stream.
std::ostream& operator<<(std::ostream& os, const BaseManip& bm)
{
bm.apply(os);
return os;
}
// convience function, so we can do std::cout << base(16) << 100;
BaseManip base(int b)
{
return BaseManip(b);
}
// A custom number output facet. These are used by the std::locale code in
// streams. The num_put facet handles the output of numberic values as characters
// in the stream. Here we create one that knows about our custom manipulator.
struct BaseNumPut : std::num_put<char>
{
// These absVal functions are needed as std::abs doesnt support
// unsigned types, but the templated doPutHelper works on signed and
// unsigned types.
unsigned long int absVal(unsigned long int a) const
{
return a;
}
unsigned long long int absVal(unsigned long long int a) const
{
return a;
}
template <class NumType>
NumType absVal(NumType a) const
{
return std::abs(a);
}
template <class NumType>
iter_type doPutHelper(iter_type out, std::ios_base& str, char_type fill, NumType val) const
{
// Read the value stored in our xalloc location.
const int base = str.iword(BaseManip::getIWord());
// we only want this manipulator to affect the next numeric value, so
// reset its value.
str.iword(BaseManip::getIWord()) = 0;
// normal number output, use the built in putter.
if (base == 0 || base == 10)
{
return std::num_put<char>::do_put(out, str, fill, val);
}
// We want to conver the base, so do it and output.
// Base conversion code lifted from Nawaz's answer
int digits[CHAR_BIT * sizeof(NumType)];
int i = 0;
NumType tempVal = absVal(val);
while (tempVal != 0)
{
digits[i++] = tempVal % base;
tempVal /= base;
}
// Get the format flags.
const std::ios_base::fmtflags flags = str.flags();
// Add the padding if needs by (i.e. they have used std::setw).
// Only applies if we are right aligned, or none specified.
if (flags & std::ios_base::right ||
!(flags & std::ios_base::internal || flags & std::ios_base::left))
{
std::fill_n(out, str.width() - i, fill);
}
if (val < 0)
{
*out++ = '-';
}
// Handle the internal adjustment flag.
if (flags & std::ios_base::internal)
{
std::fill_n(out, str.width() - i, fill);
}
char digitCharLc[] = "0123456789abcdefghijklmnopqrstuvwxyz";
char digitCharUc[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char *digitChar = (str.flags() & std::ios_base::uppercase)
? digitCharUc
: digitCharLc;
while (i)
{
// out is an iterator that accepts characters
*out++ = digitChar[digits[--i]];
}
// Add the padding if needs by (i.e. they have used std::setw).
// Only applies if we are left aligned.
if (str.flags() & std::ios_base::left)
{
std::fill_n(out, str.width() - i, fill);
}
// clear the width
str.width(0);
return out;
}
// Overrides for the virtual do_put member functions.
iter_type do_put(iter_type out, std::ios_base& str, char_type fill, long val) const
{
return doPutHelper(out, str, fill, val);
}
iter_type do_put(iter_type out, std::ios_base& str, char_type fill, unsigned long val) const
{
return doPutHelper(out, str, fill, val);
}
};
} // namespace StreamManip
int main()
{
// Create a local the uses our custom num_put
std::locale myLocale(std::locale(), new StreamManip::BaseNumPut());
// Set our locacle to the global one used by default in all streams created
// from here on in. Any streams created in this app will now support the
// StreamManip::base modifier.
std::locale::global(myLocale);
// imbue std::cout, so it uses are custom local.
std::cout.imbue(myLocale);
std::cerr.imbue(myLocale);
// Output some stuff.
std::cout << std::setw(50) << StreamManip::base(2) << std::internal << -255 << std::endl;
std::cout << StreamManip::base(4) << 255 << std::endl;
std::cout << StreamManip::base(8) << 255 << std::endl;
std::cout << StreamManip::base(10) << 255 << std::endl;
std::cout << std::uppercase << StreamManip::base(16) << 255 << std::endl;
return 0;
}
Custom manipulators are indeed possible. See for example this question. I'm not familiar with any specific one for universal bases.
You really have two separate problems. The one I think you're asking about is entirely solvable. The other, unfortunately, is rather less so.
Allocating and using some space in the stream to hold some stream state is a problem that was foreseen. Streams have a couple of members (xalloc, iword, pword) that let you allocate a spot in an array in the stream, and read/write data there. As such, the stream manipulator itself is entirely possible. You'd basically use xalloc to allocate a spot in the stream's array to hold the current base, to be used by the insertion operator when it converts a number.
The problem for which I don't see a solution is rather simpler: the standard library already provides an operator<< to insert an int into a stream, and it obviously does not know about your hypothetical data to hold the base for a conversion. You can't overload that, because it would need exactly the same signature as the existing one, so your overload would be ambiguous.
The overloads for int, short, etc., however, are overloaded member functions. I guess if you wanted to badly enough, you could get by with using a template to overload operator<<. If I recall correctly, that would be preferred over even an exact match with a non-template function as the library provides. You'd still be breaking the rules, but if you put such a template in namespace std, there's at least some chance that it would work.
I attempted to write a code, and its working with some limitations. Its not stream manipulator as such, as that is simply not possible, as pointed out by others (especially #Jerry).
Here is my code:
struct base
{
mutable std::ostream *_out;
int _value;
base(int value=10) : _value(value) {}
template<typename T>
const base& operator << (const T & data) const
{
*_out << data;
return *this;
}
const base& operator << (const int & data) const
{
switch(_value)
{
case 2:
case 4:
case 8: return print(data);
case 16: *_out << std::hex << data; break;
default: *_out << data;
}
return *this;
}
const base & print(int data) const
{
int digits[CHAR_BIT * sizeof(int)], i = 0;
while(data)
{
digits[i++] = data % _value;
data /= _value;
}
while(i) *_out << digits[--i] ;
return *this;
}
friend const base& operator <<(std::ostream& out, const base& b)
{
b._out = &out;
return b;
}
};
And this is the test code:
int main() {
std::cout << base(2) << 255 <<", " << 54 << ", " << 20<< "\n";
std::cout << base(4) << 255 <<", " << 54 << ", " << 20<< "\n";
std::cout << base(8) << 255 <<", " << 54 << ", " << 20<< "\n";
std::cout << base(16) << 255 <<", " << 54 << ", " << 20<< "\n";
}
Output:
11111111, 110110, 10100
3333, 312, 110
377, 66, 24
ff, 36, 14
Online demo : http://www.ideone.com/BWhW5
Limitations:
The base cannot be changed twice. So this would be an error:
std::cout << base(4) << 879 << base(8) << 9878 ; //error
Other manipulator cannot be used after base is used:
std::cout << base(4) << 879 << std::hex << 9878 ; //error
std::cout << std::hex << 879 << base(8) << 9878 ; //ok
std::endl cannot be used after base is used:
std::cout << base(4) << 879 << std::endl ; //error
//that is why I used "\n" in the test code.
I don't think that syntax is possible for arbitrary streams (using a manipulator, #gigantt linked an answer that shows some alternative non-manipulator solutions). The standard manipulators merely set options that are implemented inside the stream.
OTOH, you could certainly make this syntax work:
std::cout << base(4, 20);
Where base is an object that provides a stream insertion operator (no need to return a temporary string).