2

This is a code i did for practice. when i compile this, it wldnt allow cin >> choice to be compiled. It says "Error 2 error C2088: '>>' : illegal for class" and "Error 1 error C2371: 'choice' : redefinition; different basic types" Can i get some advise on how to solve this? much appreciated!

#include <iostream>

using namespace std;

int main()
{
    cout << "Difficulty levels\n\n";
    cout << "Easy - 0\n";
    cout << "Normal - 1\n";
    cout << "Hard - 2\n";

    enum options { Easy, Normal, Hard, Undecided };
    options choice = Undecided;
    cout << "Your choice: ";
    int choice;
    cin >> choice;

    switch (choice)
    {
    case 0:
        cout << "You picked Easy.\n";
        break;
    case 1:
        cout << "You picked Normal. \n";
        break;
    case 2:
        cout << "You picked Hard. \n";
        break;
    default:
        cout << "You made an illegal choice.\n";
    }

    return 0;
}
songyuanyao
  • 169,198
  • 16
  • 310
  • 405

2 Answers2

6

It says "Error 2 error C2088: '>>' : illegal for class" and "Error 1 error C2371: 'choice' : redefinition; different basic types" Can i get some advise on how to solve this?

Sure, let us see what you wrote:

...
options choice = Undecided;
// ^^^^^^^^^^^
cout << "Your choice: ";
int choice;
// ^^^^^^^^
cin >> choice;
..

This is a mistake. First, you should define the same variable only once. Second, enumerators do not have the operator>> overloaded, so you cannot use the former declaration.

The solution is to remove the former, so you would be writing this overall (with the ugly indent fixed):

main.cpp

#include <iostream>

using namespace std;

int main()
{
    enum options { Easy, Normal, Hard, Undecided };
    cout << "Difficulty levels\n\n";
    cout << "Easy - " << Easy << "\n";
    cout << "Normal - " << Normal << "\n";
    cout << "Hard - " << Hard << "\n";
    cout << "Your choice: ";
    int choice;
    cin >> choice;

    switch (choice)
    {
    case Easy:
        cout << "You picked Easy.\n";
        break;
    case Normal:
        cout << "You picked Normal.\n";
        break;
    case Hard:
        cout << "You picked Hard.\n";
        break;
    default:
        cout << "You made an illegal choice.\n";
    }

    return 0;
}

Output

g++ main.cpp && ./a.out 
Difficulty levels

Easy - 0
Normal - 1
Hard - 2
Your choice: 0
You picked Easy.
László Papp
  • 51,870
  • 39
  • 111
  • 135
  • In regards to the original question, this is definitely the best answer. – Thomas Apr 18 '14 at 06:48
  • @Thomas: was not the question titled "cin >> operand cannot work with enum"? – Tony Delroy Apr 18 '14 at 07:15
  • @TonyD Your answer is the most technically elegant but, if this is a beginner, might be a bit much. I love your answer in that regard but for the general learning user, this would be the answer I go with. – Thomas Apr 18 '14 at 07:17
  • Yes, I agree with Thomas. Tony has a nice answer, but it might be too much for a newcomer just trying to fix a compilation error quickly. But I think Tony's answer is still useful because it reveals the generic operator>> overloading mechanism for enums, although, I think, there might be some answers for that generic question already. – László Papp Apr 18 '14 at 07:21
4

You could write your own operator so you don't need to read an integer - here's one approach:

bool consume(std::istream& is, const char* p)
{
    while (*p)
        if (is.get() != *p++)
        {
            is.setstate(std::ios::failbit);
            return false;
        }
    return true;
}

std::istream& operator>>(std::istream& is, options& o)
{
     switch (is.get())
     {
        case 'E': if (consume(is, "asy") { o = Easy; return is; } break;
        case 'H': if (consume(is, "ard") { o = Hard; return is; } break;
        case 'N': if (consume(is, "ormal") { o = Normal; return is; } break;
        case 'U': if (consume(is, "ndecided") { o = Undecided; return is; } break;
     }
     is.setstate(std::ios::failbit);
     return is;
}

Similarly you can write an output operator:

std::ostream& operator<<(std::ostream& os, options o)
{
    return os << (o == Easy ? "Easy" :
                  o == Hard ? "Hard" :
                  o == Normal ? "Normal" :
                  o == Undecided ? "Undecided" :
                                   "<invalid option>");
}

These allow for:

enum options { Easy, Normal, Hard, Undecided };

...streaming operators go here...

int main()
{
    cout << "Difficulty levels\n\n";
    cout << "Easy\n";
    cout << "Normal\n";
    cout << "Hard\n";

    options choice = Undecided;
    cout << "Your choice: ";
    if (cin >> choice)
        cout << "You picked " << choice << '\n';
    else
        cout << "Error while reading your choice.\n";
}
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Tony, be careful with precedence. "<<" has precedence over the ternary operator. Also, I think chained ternary operation is not so comprehensive for many people. Unfortunately, C++ does not support anything like what rust has in this regard for functional programming. Still, I personally prefer condition statements separately for readability, but that is just my personal taste. The precedence issue is real, however. – László Papp Apr 18 '14 at 06:51
  • @LaszloPapp yeah - I suspected as much when I wrote it but couldn't be bothered looking it up, and I generally prefer less cluttered code even if it means reacting to a compilation error or two. Doesn't necessarily say much for readability, but in this kind of usage there's only one thing it could be trying to do. People should learn the ternary operator - sooner the better. Cheers. – Tony Delroy Apr 18 '14 at 07:14
  • Fwiw, I did not try to compile, just remembered from experience stumbling upon this. :P – László Papp Apr 18 '14 at 07:15