How do I increment an enum in VS C++ 6.0? - c++

I copy and pasted some code that increments an enum:
myenum++;
This code worked fine as it was compiled in VS.NET C++ 2003
I am now developing in VS 6.0 and get the error:
error C2676: binary '++' : 'enum
ID' does not define this
operator or a conversion to a type
acceptable to the predefined operator
How can I get this to behave the same in 6.0?

I see nothing wrong with defining operator++ on a well understood enum. Isn't that the purpose of operator overloading? If the context made no sense (e.g. an enum with holes in it), then of course it doesn't make sense. Defining operator* for a class called Complex that implement complex numbers is not just valid but a great application of mathematical operator overloading in C++!
If the developer defines an enum where operator++ makes obvious and intuitive sense to the clients of that enum, then that's a good application of that operator overload.
enum DayOfWeek {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday};
inline DayOfWeek operator++(DayOfWeek &eDOW, int)
{
const DayOfWeek ePrev = eDOW;
const int i = static_cast<int>(eDOW);
eDOW = static_cast<DayOfWeek>((i + 1) % 7);
return ePrev;
}

an enum may be intergral but it doesn't mean it covers a continuous range.
This
enum {
A,
B,
C,
}
May Will default to
enum {
A = 0,
B = A + 1,
C = B + 1,
}
and so you could get away with
int a = A;
a++;
However if you have
enum {
A = 2,
B = 4,
C = 8,
}
now +1 ain't gonna work.
Now, if you also had things like
enum {
FIRST,
A = FIRST,
B,
C,
LAST = C
}
then when iterating the enum would you do A and C twice?
What is the purpose of iterating the enum? do you wish to do 'for all' or for some subset, is there actually an order to the enum?
I'd throw them all in a container and iterate that instead
unordered - use a set
ordered - a vector or list

Please try to convert to int, add one (+1) and convert back to the enum.

myenum=(myenum_type)((int)myenum+1);
It's ugly but it works.

Related

Safely convert enum class from underlying type

Let's say I have a strongly typed enum type like this:
enum class message : int {
JOIN = 0,
LEAVE = 4,
SPAWN = 1,
}
And I need to safely (safely in this case means discarding invalid variants) convert it from it's underlying type (int).
For this purpose, I have a function to convert it for me:
std::optional<message> get_message(int num) {
return num == (int)message::JOIN || num == (int)message::LEAVE || num == (int)message::SPAWN ? (message)num : {};
}
This works, but is long to write and prone to mistakes, especially for enums with a larger number of variants.
Is there a way to automate this process in C++17?
Talking about underlying type, we notice that this class merely obtains a type using another type as model, but it does not transform values or objects between those types.
As an option to simplify the function you could work by iterating in the enum,or as others said before with some type of container, by iterating the same enum as an example here: How can I iterate over an enum?
and more information about enum just in case: https://learn.microsoft.com/en-us/cpp/cpp/enumerations-cpp?view=vs-2019

Avoid hardcoding enum type

In c++11 code it would be nice to avoid mentioning a specific enum qualifier every time I use the enum value - as it is a new code and it is refactored a lot.
For that purpose is it possible something in the spirit of the last line of this pseudo code:
enum abc { a,b,c };
// some long code of events which returns the enum's value
auto e = []()->abc{return abc::b;}();
if (e == std::declval(e)::a) { ...
If not possible in C++11 will it become possible in C++14 or 17?
You're close, you can use decltype:
if (e == decltype(e)::a) {
...

C++11 Automate creation of integer to enum value map

I need to create a map of int to enum values. (I'm reading integers in a file and need to create an enum from them at runtime.) I can manually create a map as shown in my example below. However this is a trivial example with only a few (i.e., seven) elements of my enum.
My real-world-problem has several hundred elements of my enum class. I don't need to print the names of my real-world enum, but I do need to get the enum value given an integer. I already have the enum class created and want an automatic way to create a map from an integer to the enum value.
I'm looking to automate the creation of the map which I've called WeekMap so I can pass it an integer and get the enum value. Is this even possible? Please tell me it is.
// Compile with:
// clang++ -std=c++11 -stdlib=libc++ enum_test.cpp -o enum_test
//
#include <iostream>
#include <string>
#include <map>
enum class Days {
SUNDAY = 1,
MONDAY = 2,
TUESDAY = 3,
WEDNESDAY = 4,
THURSDAY = 5,
FRIDAY = 6,
SATURDAY = 7
};
std::ostream& operator<< (std::ostream& os, const Days& day){
os << static_cast<std::underlying_type<Days>::type>(day);
return os;
}
std::map<unsigned int, Days> WeekMap{
{1, Days::SUNDAY},
{2, Days::MONDAY},
{3, Days::TUESDAY},
{4, Days::WEDNESDAY},
{5, Days::THURSDAY},
{6, Days::FRIDAY},
{7, Days::SATURDAY},
};
// Return the day of the week
Days WhatDay(unsigned int D){
return WeekMap[D];
}
int main() {
std::cout << "\nLearning how to 'cout' enums." << std::endl;
Days myDay = Days::MONDAY;
std::cout << "\nMonday is day: " << myDay << "\n" << std::endl;
for (int i=1; i<8; i++){
std::cout << "Day number: " << i << " is " << WhatDay(i) << std::endl;
}
return 0;
}
You do not need the map. Your WhatDay function can be written like this:
Days WhatDay (unsigned int D) {
return static_cast<Days>(D);
}
This is basically free (in efficiency terms.) But you might want to make sure your enum's underlying type is indeed an int (or something smaller or larger;) again for efficiency reasons and for reliability reasons:
enum class Days : int {
...
};
What you will lose, however, with this method is error checking. You won't be able to check whether the integer is a valid enumeration value or not; especially if your enum values are not contiguous.
UPDATE 2 (Update 1 is below!)
To somewhat automate creation of this kind of enum, and a whole lot of other code, you can use the following technique:
You first write down the data you are interested in, in a general format:
#define EXPAND_VALUES(action) \
action (1, SUNDAY, "Sunday") \
action (2, MONDAY, "Monday") \
action (3, TUESDAY, "Tuesday") \
action (4, WEDNESDAY, "Wednesday") \
action (5, THURSDAY, "Thursday") \
action (6, FRIDAY, "Friday") \
action (7, SATURDAY, "Saturday")
// Note the lack of a separator after the entries; this is more flexible.
This is all the information I have about each of the entries, in a general form (i.e. passed to an unknown function-like thing called action.
Now, to define the enumeration, we can simply say:
#define DEF_ENUM(i,v,s) v = i,
enum class Days : int { EXPAND_VALUES(DEF_ENUM) };
#undef DEF_ENUM
As further examples, you can define the map you want, and another table that maps enum values to strings like this:
#define DEF_MAP(i,v,s) {i, Days::v},
std::map<int, Days> WeekMap { EXPAND_VALUES(DEF_MAP) };
#undef DEF_MAP
#define DEF_STR_MAP(i,v,s) {Days::v, s},
std::map<Days, std::string> WeekStrMap { EXPAND_VALUES(DEF_STR_MAP) };
#undef DEF_STR_MAP
(This sample code is available on Ideone.)
Note what this technique does for you. Without any redundancy in data definition, you get as many data-structure definitions, array initializations, switch-statement cases, if-else if-else constructs, etc. you want out of that data. And all of this is done at compile time (or before) without any hassles.
This is an extremely powerful technique that might (or might not) be useful to you.
UPDATE 1 (In response to the updated question):
No, it is not possible to create an enum at runtime in C++. You cannot create a new type for the compiler at runtime, when there is no more compiler (if this is really what you're after.)
However, since enums in C++ offer absolutely no runtime facilities, then, at runtime, there is no difference between two enums with the same underlying type. Or in fact, between an enum and an int (if int is the underlying type for that enum.)
Therefore, I propose this: you define an empty enum, and write the WhatDay function exactly as before. And everything will be fine! (Since you don't need bounds checking.)
Specifically, what I'm proposing is this:
enum class Days : int { /*really, really empty!*/ };
Days WhatDay (unsigned int D) {
return static_cast<Days>(D);
}
This works because it seems to me that you do not know your enumeration values at compile time, and the compiler doesn't care one bit for the values of an enum at runtime. No one does!
And if you want error and range checking, I suggest you use an "Interval Tree" (read up on it on Wikipedia.) You populate this tree when you read your enum values from your file at runtime (and this is the only data structure you populate,) and then check each value passed to the WhatDay function against it.

Using enum in loops and value consistency

I'm a big fan of C++'s strong-typing features and what I like the most is to use enumerations while dealing with limited sets of data.
But enumerations lack some useful features, for example operators:
enum class Hex : int
{
n00, n01, n02, n03,
n04, n05, n06, n07,
n08, n09, n10, n11,
n12, n13, n14, n15
};
for (Hex h = Hex::n0; h <= Hex::n15; ++h) // Oops! no 'operator ++'
{ /* ... */ }
Is easy to get rid of the lack of operators creating a free operator on the same scope:
Hex &operator ++(Hex &h)
{
int r = static_cast<int>(Hex);
h = static_cast<Hex>(r + 1);
return h;
}
for (Hex h = Hex::n0; h <= Hex::n15; ++h) // Now the '++h' works!
{
std::cout << std::dec << int(h) << ": "
<< std::hex << int(h) << '\n';
}
But this approach is more a nuisance than a solution, because it can break the value limitation of the enumeration: applying ++h while h equals to Hex::n15 will set h to he value 16, wich is out of the Hex scope of values while h is still of the type Hex!, This problem is more evident in other enumerations:
enum class Prime : int
{
n00 = 2, n01 = 3, n02 = 5, n03 = 7,
n04 = 11, n05 = 13, n06 = 17, n07 = 19,
n08 = 23, n09 = 29, n10 = 31, n11 = 37,
n12 = 41, n13 = 43, n14 = 47, n15 = 53
};
Prime &operator ++(Prime &p)
{
// How to implement this?! will I need a lookup table?
return p;
}
This problem was a surprise for me; I was betting that storing an incorrect value into an enumeration value will throw an exception. So, for now I was wondering if there's an elegant way to deal with this enumeration's weaknesses, the goals I want to achieve are:
Find a comfortable way to use enumeration values in loops.
Ensuring enumation data consistency between operations.
Additional questions:
Is there a reason for not throwing an exception when an enumeration data gets a value that is out of its possible values?
There is a way to deduce the type associated with an enumeration class?, the int type in the enumerations Hex and Prime.
As you've noticed, enum in C++ is not an enumerated type,
but something more complex (or more mixed). When you define an
enum, you define in fact two things:
An integral type with a legal range sufficient to contain an
or of all of the enumerated values. (Technically: the range
is 2^n - 1, where n is the number of bits necessary to
hold the largest value.)
A series of named constants having the newly defined type.
(I'm not sure what happens with regards to the range if you
explicitly specify an underlying type.)
Given your enum Prime, for example, the legal values would be
all integers in the range [0...64), even if all of these
values don't have a name. (At least if you didn't specifically
say that it should be an int.)
It's possible to implement an iterator for enums without
initializers; I have a program which generates the necessary
code. But it works by maintaining the value in an integral type
which is large enough to contain the maximum value plus one. My
machine generated implementations of ++ on such an enum will
assert if you try to increment beyond the end. (Note that
your first example would require iterating h one beyond the
last value: my implementation of the various operators does not
allow this, which is why I use an iterator.)
As to why C++ supports the extended range: enum are often used
to define bit masks:
enum X
{
a = 0x01,
b = 0x02,
c = 0x04,
all = a | b | c,
none = 0
};
X operator|( X lhs, X rhs )
{
return X((int)lhs | (int)rhs);
}
// similarly, &, |= and &=, and maybe ~
One could argue that this use would be better handled by
a class, but the use of enum for it is ubiquitous.
(FWIW: my code generator will not generate the ++, -- and
the iterators if any of the enum values has an explicitly
defined value, and will not generate |, & etc. unless all of
the values have explicitly defined values.)
As to why there is no error when you convert some value outside
the legal range (e.g. 100, for X, above) is simply in keeping
with the general philosophy inherited from C: it's better to be
fast than to be correct. Doing extra range checking would
entail additional runtime cost.
Finally with regards to your last example: I don't see this as
a realistic use of enum. The correct solution here is an
int[]. While the C++ enum is rather a mixed breed, I would
only use it as a real enumerated type, or for bit masks (and
only for bit masks because it is such a widely established
idiom).
You can use a switch:
class Invalid {};
Prime& operator ++(Prime& p)
{
switch(p)
{
case n00: return n01;
case n01: return n02;
case n02: return n03;
case n03: return n04;
case n04: return n05;
case n05: return n06;
case n06: return n07;
case n07: return n08;
case n08: return n09;
case n09: return n10;
case n10: return n11;
case n11: return n12;
case n12: return n13;
case n13: return n14;
case n14: return n15;
// Here: 2 choices: loop or throw (which is the only way to signal an error here)
case n15: default: throw Invalid();
}
}
But note that this is not the right use of enums. I personally find this error-prone. If you want to enumerate integers, you can use an array of ints to do this, or for the case of prime numbers, a function (in mathematical sense: int nextPrime(int)).

Given a pointer to a C++ object what are all the correct ways to call the operator[] function?

I am writing a time varying profile class using templates and want to index the profile by either a numeric index or by a date and time as represented by a struct tm. The indexing by a numeric index works fine, but the indexing by a date doesn't work with a pointer to the object. Here is some sample code containing approaches that work and approaches that don't work.
#include "profile.h" // Class Profile<T> is declared and defined here.
float f;
int i;
struct tm d;
Profile<float> p;
Profile<float> *pPtr;
// Non-pointer syntax
f = p[i]; // this works.
f = p.operator[](i); // this works, but its ugly.
f = p[d]; // this works.
f = p.operator[](d); // this works, but its ugly.
// Pointer syntax
f = (*pPtr)[i]; // this works.
f = pPtr->operator[](i); // this works, but its ugly.
f = (*pPtr)[d]; // this isn't what I typed. I did f = *(pPtr)[d];
f = pPtr->operator[](d); // this works, but its ugly.
This C++ code is being written in Visual Studio 2008. The compiler error message is error C2677 binary '[' : no global operator found which takes type 'tm' (or there is no acceptable conversion).
Given a pointer to a C++ object what are all the correct ways to call the operator[] function?
The code you've shown here is fine; probably in your previous attempts you were doing *(pPtr)[d] instead of (*pPtr)[d], which would understandably cause an error since operator* has lower precedence than operator[].
You have listed the sensible options. I don't see why the pointer dereference wouldn't work. The following compiles just fine:
std::vector<int> v;
v.push_back(0);
v[0];
std::vector<int>* vp = &v;
(*vp)[0];
In similar cases, i add additional method in class, such as 'at'.
templateType & Profile::at(int idx)
{
return operator[](idx);
}
So, code looks better :
f = pPtr->at(i);
By the way, using at(idx) in class methods (Profile in our case) would be easy that operator[](idx).