2
class Card
{
public:
    enum class Rank{ TWO = 2, THREE = 3, FOUR = 4, FIVE = 5, SIX = 6, SEVEN = 7, 
                EIGHT = 8, NINE = 9, TEN = 10, JACK = 10, 
                QUEEN = 10, KING = 10, ACE = 11 };
    Rank r;

}

Is it possible to access TEN, JACK and Queen without using Card::Rank::TEN Card::Rank::JACK Card::Rank::QUEEN Card::Rank::KING?

I am overloading ostream operator<< using a switch, but it has errors... when i try to create a constructor initializing 52 cards in class Deck, I find it impossible.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
user3390652
  • 132
  • 1
  • 13

4 Answers4

2

There is really no difference between Card::Rank::TEN, Card::Rank::JACK, Card::Rank::QUEEN and Card::Rank::KING. You cannot tell them apart.

It's the same as if you wrote

#define TEN 10
#define JACK 10
#define QUEEN 10
#define KING 10

And then programmatically trying to distinguish between them. But they contain the exact same value; they are indistinguishable.

StilesCrisis
  • 15,972
  • 4
  • 39
  • 62
1

A switch with several branches on the same value is erroneous. An enum value is just a fancy way to write an integer, so...

vonbrand
  • 11,412
  • 8
  • 32
  • 52
0

In terms of having to type Card::Rank::TEN according to one of the answers here you should be able to use Card::TEN instead, provided you declare your enum like this:

class Card
{
public:
    enum Rank { TWO = 2, THREE = 3, FOUR = 4, FIVE = 5, SIX = 6, SEVEN = 7, 
                EIGHT = 8, NINE = 9, TEN = 10, JACK = 10, 
                QUEEN = 10, KING = 10, ACE = 11 };

You can't use two of the same values in a switch statement no matter what. This is because when the code runs and you get a value 10 your code will not be able to determine if it is a Ten, Jack, Queen or a King.

Either change the values or use only one of them in your switch. Here is a contrived example:

int function(int value)
{
    int rv = 0;

    switch (value)
    {
        case 0:
            rv = 7;
            break;
        case 1:
            rv = 8;
            break;
        case 1:
            rv = 21;
            break;
        default:
            rv = 0;
            break;
    }

    return rv;
}

int main()
{
    printf("What does function(1) return? %d", function(1));

    return 0;
}

This would not make sense since we return two different values when we are passed the value 1 so the compiler does not allow it.

It is the same if you use your enum values of Card::Rank::TEN in the switch because their value is the same the compiler doesn't allow it.

Card::Rank card = Card::Rank::TEN;

switch(card)
{
    // Some cases...
    case Card::Rank::JACK:
        // Do something
        break;
    case Card::Rank::TEN: // <- not allowed since it is the same as the case for Card::Rank::JACK.
        // Do something else
        break;
    // Some more cases...
}

This isn't allowed. The following would seem like it should be ok since the compiler should be able to see that it is the same code being run for both cases but it still won't work.

switch(card)
{
    // Some cases...
    case Card::Rank::JACK:
    case Card::Rank::TEN: // <- still not allowed, even though both code paths for case 10 do the same thing...
        // Do something else
        break;
    // Some more cases...
}

and I'm sorry but I can't give good reasoning for this other than, it is probably not allowed in the standard itself for consistency. Someone else might be able to elaborate on this.

Community
  • 1
  • 1
nonsensickle
  • 4,438
  • 2
  • 34
  • 61
0

You can view enum as an aliases mechanism. So we usually use it to replace a magic number.

Thus we don't need to write something likeint card1 = 11; what is 11? We know JACK, and don't know what is 11.

The other advantage is that it limit the possible value and wont see something like int card2 = 14;

So in this view point, if J, Q and K have a same value, it would be strange because they are not presenting the same card. If you want to map a card to a value, then std::map is a good choice.

enum Rank{ TWO , THREE, FOUR, FIVE, SIX , SEVEN, ......};


static const std::map<Rank, value> = 
{
    {TWO, 2}, {THREE,3},......
};

if as d_ominic mentioned, the ACE has two value, maybe you would like to try std::multimap

Cigany
  • 178
  • 1
  • 10