How to iterate through enums

Jun 16, 2012 at 11:00am
I've been trying to figure out how to use the advantages of enums over static const unsigned variables by creating objects with them like so:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
enum eSuit
{
    SPADES,    DIAMONDS,
    CLUBS,     HEARTS
};
enum eVal
{
    ACE = 1,	
    TWO,    THREE,    FOUR,    FIVE,
    SIX,    SEVEN,    EIGHT,   NINE,
    TEN,    JACK,     QUEEN,   KING
};

class cCard
{
public:
	cCard(eSuit s, eVal n) : suit(s), num(n) {}

	eSuit suit;
	eVal num;
};


okay, no problem so far. But now if I want to make a deck with these cards, I'd want to do something like this and get the following errors:
1
2
3
4
5
6
7
8
9
10
11
class cDeck
{
    std::list<cCard> deck;
public:
    cDeck()
    {
        for (eSuit suit = SPADES; suit <= HEARTS; ++suit)
            for (eVal num = ACE; num <= KING; ++num)
                deck.push_back( cCard(suit,num) );
    }
};
1>Snippets.cpp(7): error C2675: unary '++' : 'eSuit' does not define this operator or a conversion to a type acceptable to the predefined operator
1>Snippets.cpp(8): error C2675: unary '++' : 'eVal' does not define this operator or a conversion to a type acceptable to the predefined operator


so now if I try and do something like this, I get the following errors:
1
2
3
4
5
6
7
8
9
10
11
class cDeck
{
    std::list<cCard> deck;
public:
    cDeck()
    {
        for (unsigned suit = SPADES; suit <= HEARTS; ++suit)
            for (unsigned num = ACE; num <= KING; ++num)
                deck.push_back( cCard(suit,num) );
    }
};
1>Snippets.cpp(9): error C2665: 'cCard::cCard' : none of the 2 overloads could convert all the argument types
1>          Snippets.cpp(31): could be 'cCard::cCard(eSuit,eVal)'
1>          while trying to match the argument list '(unsigned int, unsigned int)'


So my question: What's the most effective way to iterate through enums? Do I need to use the unsigned type and just cast it to the enum type when sticking it in my constructor? It works, but I was wondering if there was a more native way to do it.
1
2
3
4
5
6
7
8
9
10
11
class cDeck
{
    std::vector<cCard> deck;
public:
    cDeck()
    {
        for (unsigned suit = SPADES; suit <= HEARTS; ++suit)
            for (unsigned num = ACE; num <= KING; ++num)
                deck.push_back( cCard( (eSuit)suit, (eVal)num) );
    }
};
Last edited on Jun 16, 2012 at 11:24am
Jun 16, 2012 at 12:56pm
I think I would create a macro definition to automatically create operators for my enums so I could do ++suit and such.
Jun 16, 2012 at 1:08pm
You can overload operator ++ for enumeration type.:)
Jun 16, 2012 at 1:15pm
I wonder if ++static_cast<unsigned int> (suit) would work.
Jun 16, 2012 at 1:22pm

Catfish2 (105)

I wonder if ++static_cast<unsigned int> (suit) would work


I did not check but in my opinion it shall not work because operator ++ requires lvalue.
Jun 16, 2012 at 1:42pm
@Stewbond

try something as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum eVal
{
    ACE = 1,	
    TWO,    THREE,    FOUR,    FIVE,
    SIX,    SEVEN,    EIGHT,   NINE,
    TEN,    JACK,     QUEEN,   KING
};

eVal operator ++( eVal value )
{
	if ( value == KING ) return ( ACE );
	
	unsigned int x = value;
	return ( static_cast<eVal>( ++x ) );
}

Jun 16, 2012 at 1:45pm
Vlad is probably right, although I didn't check either.
Also following his suggestion; it's not pretty. Maybe someone has a better idea?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
enum Cards_e {
    SPADES,
    DIAMONDS,
    CLUBS,
    HEARTS
};

Cards_e operator ++ (Cards_e &c, int)
{
    switch (c)
    {
        case SPADES: c = DIAMONDS; return SPADES;
        case DIAMONDS: c = CLUBS; return DIAMONDS;
        case CLUBS: c = HEARTS; return CLUBS;
        case HEARTS: c = SPADES; return HEARTS;
        default: return c;
    }
}

Jun 16, 2012 at 5:53pm
closed account (zb0S216C)
I don't think iteration of an enumeration is allowed. Constants that are initialised with constant expressions, such as const int Constant(0), do not have memory allocated to them. Since each enumerator is assigned a magic constant by default, they won't have memory assigned to them. So how do you iterate through something that doesn't technically exist? Or have I got the wrong idea?

Wazzak
Jun 16, 2012 at 10:45pm
Hmm good points everyone. This is quite interesting. I'll try overloading the enums and see how "clean" I can make it, although I see Framework's point regarding constants. Perhaps the "right" idea is to static_cast the enum to an unsigned when iterating.
Last edited on Jun 16, 2012 at 10:48pm
Jun 16, 2012 at 11:52pm
I'd probably wrap it in a class or something if you wanted to do that.
Topic archived. No new replies allowed.