[enum class] Questions

May 26, 2017 at 7:03pm
Hello,

I'm currently working on a program that is supposed to use an enumerator type to step through an array of structures. No real problem there. Since my book suggests the use of strongly typed enumerators, or enum class, without going into too much detail about how exactly they work, I wanted to use it instead.

Below is short but working example of the way I have come up with to use enum class to step through an array. (works for array of structures as well ...)

Here is a link to cpp shell: http://cpp.sh/7f53r [since I do not know how to use it here...] :-)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <iomanip>
#include <string>

enum class monthNames : int
{
	JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY,
	AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER
};

int main()
{
	const int MONTHS = 12;

	int yearStart = static_cast<int>(monthNames::JANUARY);
	int yearEnd = static_cast<int>(monthNames::DECEMBER);

	std::string data[MONTHS] = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY",
									"JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER",
									"NOVEMBER", "DECEMBER" };

	for (; yearStart <= yearEnd; yearStart++)
	{
		std::cout << "The month names are: " << data[yearStart] << "\n";
	}

	return 0;
}


Is this generally the right/a good/or even correct approach? Or is there a better more correct way to do it?
Last edited on May 26, 2017 at 7:05pm
May 26, 2017 at 7:26pm
With the code you posted there is really no need for the enum class as you can just iterate through the array.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
{

	std::string data[] = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY",
                           "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER",
                           "NOVEMBER", "DECEMBER" };

	for (auto& month : data)
	{
		std::cout << "The month names are: " << month << "\n";
	}

	return 0;
}


May 26, 2017 at 7:34pm
Hello jlb,

I have written this example to demonstrate my general approach. The only really important part there is the typecast and enum class definition. I chose to use an array because - give or take - the enum class is supposed to be doing basically the same thing for my array of structures: Stepping through the array.

Again, I just wish to make sure that above approach is actually correct, and/or how to do it differently if it isn't. :-)
Last edited on May 26, 2017 at 7:36pm
May 27, 2017 at 8:23pm
I chose to use an array because - give or take - the enum class is supposed to be doing basically the same thing for my array of structures: Stepping through the array.

Again, I just wish to make sure that above approach is actually correct, and/or how to do it differently if it isn't.

From my inexperienced point of view, your code is correct; but there’s a point you need to pay attention to.
You code works because there aren’t ‘holes’ in your enumeration - it’s a progressive sequence of ints. But, if you use this approach, you need to guarantee that you’ll never modify that enumeration, or, if you modify it, it will remain a sequence without ‘holes’.
For clearness sake: a loop like, for example, a for-loop will fail if the enumeration has ‘holes’.

Enumerations are useful to ignore the numbers that are ‘behind’ them, which very often are not a sequence, or at least aren’t a sequence of ‘+1’. E.g.:
1
2
3
4
5
6
enum class MyFlags { OPERATION_OK,
                     OPERATION_IN_PROGRESS,
                     OPERATION_PAUSED,
                     OPERATION_RESTORED         =   4,
                     OPERATION_MISSED_VALUE     =   8,
                     OPERATION_ERROR            =   16 }

That’s a feature that helps, for example a team of programmers, to keep the code consistent even when new MyFlags are added from some of them.

My personal conclusion is: I can’t see any error in your code, but as far as I can see its main advantage consists in a neater syntax when randomly accessing an array, not when getting through it by a loop.

Anyway, again just as a personal matter of preference, I’d suggest you to develop some strategies to cut down on “casts”, which are IMHO the opposite of clearness.
Here an example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <limits>
#include <string>
#include <vector>

enum class MonthNames : int { JANUARY, FEBRUARY, MARCH, 
                              APRIL, MAY, JUNE, 
                              JULY, AUGUST, SEPTEMBER, 
                              OCTOBER, NOVEMBER, DECEMBER };

int main()
{
    std::vector<std::string> data = { "JANUARY", "FEBRUARY", "MARCH", 
                                      "APRIL", "MAY", "JUNE", 
                                      "JULY", "AUGUST", "SEPTEMBER", 
                                      "OCTOBER", "NOVEMBER", "DECEMBER" };

    for (int i {0}; i <= static_cast<int>(MonthNames::DECEMBER); i++) {
        std::cout << "The month names are: " << data.at(i) << '\n';
    }

    std::cout << "\nPress ENTER to continue...\n";
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    return 0;
}


If you fancy reading more about enumeration, I strongly suggest you this article, which also comes up with a great code, at the end.
http://www.drdobbs.com/when-enum-just-isnt-enough-enumeration-c/184403955
May 28, 2017 at 5:37pm
Hello Enoizat!

Thanks for your reply! I do see that enum class doesn't seem to be the best choice for looping through an array of structures. Yet I do feel, but have no confirmation for it actually being true, that, with an enum class, in a for loop, the array can never go out of bounds when stepping through it. Meaning that the first element and the last element in the enumerator class sets the limit. Of course that probably only is the case when both array and enum class contain the same amount of elements. (And, as you mentioned, the enumerator members are contiguous.) Or that, if they differ, only the number of elements can and will be accessible, specified in the enum class. (I hope I make sense).

Ex.: array[12], enum numbers { ONE, TWO, THREE, FOUR, FIVE };
In a loop, to my understanding, only items 0 to 4 would be displayed, whatever they might be, correct?

In my example, and in the program it was supposed to be used in, the enumerators were contiguous. (Months in both cases). The only difference being that in this example I chose to use a simple array, while my program uses array of structures.

-

I do agree as far as typecasting goes. With enumerator data type I can get by without casting. Below code-snippet being an example:

1
2
3
4
5
6
7
8
9
10
11
12
for (int index = JANUARY; index <= DECEMBER; index++)
{
   // Do stuff
}

My book on the other hand explains it like this:

[code]
for (months = JANUARY; months <= DECEMBER; months = static_cast<monthNames>(months + 1)
{
   // Do stuff
}


As an aside: When hovering over January, in my IDE, I also noticed that it has a similar call of sorts as it looks like would it be an enumerator class: enumName::JANUARY

Ultimately, for the programming project it was meant to be used in, I decided to go with enumerator data type.

-

What I learned from your article, of which the code listings are a case in point of 'code = too advanced for my current level of understanding', is, that, even those purposes I had in mind for as ideal candidates for an enum class, aren't very well suited. For instance in a menu-driven program. The code becomes verbose very quickly, and looks rather clunky ...

Yet, going by what you said, and I allow myself to quote you:

My personal conclusion is: I can’t see any error in your code, but as far as I can see its main advantage consists in a neater syntax when randomly accessing an array, not when getting through it by a loop.


Enumerator class would make it the perfect fit for my current project. (Once I find a way to implement what I have in mind.) It involves allowing a user to alter data in an array of structures after all data has been entered. Meaning, each member of an array of structures should be accessible and alterable. (Not sure how I would pull this off in practice, but, I will (have to) find a way to make it happen. :-))

Btw. If you, or any other member of this most helpful community, would happen to know of any other web-resources I can learn more about enum class, please go ahead and provide a link to it. (Resource-Language doesn't matter). The only important thing is that it is newbie friendly, or more precisely tailored to my current level, in case it contains code listings ... (I tried, but failed miserably, to find what I was looking for.)
Last edited on May 28, 2017 at 5:38pm
Topic archived. No new replies allowed.