...no match for 'operator>>'...

I'm so new to this that I doubt I'll even understand the answer, but since one guy in my ITV C++ class has already turned in this assignment before we've been taught a thing the teacher wants the rest of us to catch up. I commented the line with the error. I'm probably doing the rest of it wrong also, but please don't overwhelm me. Here's the code:
// Menu Chooser rewrite, p70-1
// Would demonstrate the switch statement and enumeration if I had a clue

#include <iostream>

using namespace std;

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

enum choice {easy = 1, normal, hard};
choice level;

cout << "Choice: ";
cin >> level; // error reads "...no match for 'operator>>' in 'std::cin >> level'", whatever that means...

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

cout << "Press ENTER to continue...";
cin.ignore(cin.rdbuf()->in_avail() + 1);

return 0;
}

Thanks in advance!
choice level is not a valid declaration. Change it to this. int level;]
And that enum is unnecessary, too.
To be more clearer, an enum type variable can not be used with "cin". That is what the error says.
Though I never used it such way, I dont think it is right for cin operation.
But you can use those enum variables and expression in conditional statements though.

Simply, change the type of level from choice to int (as suggested above) and remove the enum at all as you are not using except declaring the 'level', and then run it again.

Good luck :)
Rather than complain about stuff that is perfectly valid, why not address the OP's problem?

You can do as satm2008 suggests to just get input as an int, or you can overload the extraction operator to work with a choice.
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// Menu Chooser rewrite, p70-1
// Would demonstrate the switch statement and enumeration if I had a clue

#include <iostream>
#include <limits>

using namespace std;

// Here the 'choice' type is declared globally, so we can provide an extraction operator for it
enum choice {easy = 1, normal, hard};

// And here is the operator itself.
// This is actually a very simple version, but it complies to your program's specification.
// You could add the power to enter "easy", etc as strings also..
// Whatever you like is possible.
//
// Notice how if anything goes wrong, one of the fail bits gets set and the target is not modified.
// That is how all extraction operators should work.
//
istream& operator >> ( istream& ins, choice& c )
{
  int i;
  if (ins >> i)
  {
    // (See the notes following this [code] block for more about the assumptions made here)
    if ((i < easy) || (i > hard)) ins.setstate( ios::badbit );
    else c = (choice)i;
  }
  return ins;
}

int main()
{
  // (Don't forget to apply some indentation to your source code.)
  cout << "Difficulty Levels\n\n";
  cout << "1 - Easy\n";
  cout << "2 - Normal\n";
  cout << "3 - Hard\n\n";

  choice level;

  cout << "Choice: ";
  cin >> level;
  if (!cin.good())
  {
    // If the user entered something wrong, make sure 'level' has a bad
    // value. (More on this in the notes that follow.)
    level = (int)hard +1;
    // And reset the input stream so that it can work again. The 'ignore'
    // that follows is important, but since we do it either way it is not
    // necessary to put it inside this block.
    cin.clear();
  }
  // Since reading a 'choice' doesn't read the ENTER that the user pressed
  // after typing his selection, we need to get rid of it. (And any erroneous input.)
  cin.ignore( numeric_limits <streamsize> ::max(), '\n' );

  // Having gone through the trouble of creating an enum for
  // your values, you might as well use them:
  switch (level)
  {
  case easy:
    cout << "You picked Easy." << endl;
    break;
  case normal:
    cout << "You picked Normal." << endl;
    break;
  case hard:
    cout << "You picked Hard." << endl;
    break;
  default:
    cout << "You made an illegal choice." << endl;
  }

  // (See the notes that follow about the numeric limits thing)
  cout << "Press ENTER to continue...";
  cin.ignore( numeric_limits <streamsize> ::max(), '\n' );

  return 0;
}


Note 1: Enumerations
The purpose of an enumeration is to abstract away numeric constants into a friendly, human-readable name. Once the enum is defined the programmer shouldn't have to concern himself with the actual values of its parts.

In your program, you are treating the enum as if it were an integer --meaning that you still care about its values. Don't.

The extraction operator happens to know that choice is actually an enum, but that is only because of convenience, since the user's input directly matches the enum value. This is one place where that is fine, but again, you could easily make it properly abstract.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
istream& operator >> ( istream& ins, choice& c )
  {
  int i;
  ins >> i;
  if (ins)
    switch (i)
      {
      case 1:  c = easy;   break;
      case 2:  c = normal; break;
      case 3:  c = hard;   break;
      default: ins.setstate( ios::badbit );
      }
  return ins;
  }

In your switch across the choices, you have a select case for every possible choice, and then a default. But technically there shouldn't be any bad values. I manufactured one by assigning it an improper value (line 48), but if an enumeration is expected to have bad values then one should be explicitly defined:

enum choice {nolevel, easy, normal, hard};

Now you can use it and just automatically handle cin for potential failure.
1
2
3
4
5
6
choice level = nolevel;

cin >> level;

cin.clear();
cin.ignore( ... );
Or:
1
2
3
4
5
6
choice level;

if (!(cin >> level)) level = nolevel;

cin.clear();
cin.ignore( ... );


Note 2: stream sizes
Unfortunately, in_avail() is not very useful. It only tells you if there is anything sitting in the read buffer. It doesn't actually tell you if there is more input waiting to be read.

Further, it is not defined on cin, and different implementations are notoriously spotty about how they implement it. For example, MinGW will always return 0, no matter what.

Instead of messing with that, just ignore everything up to and including the next ENTER keypress (which is translated into a newline '\n'). If the input really has terminated then it will still behave properly.

The most general way is to ignore a maximum of 'as many characters are possible in an input stream', in other words, numeric_limits<streamsize>::max()

Hope this helps.
Thank you to everyone for responding.

The reason for the enumeration is that the assignment required it. The original program example from the text was to have enumeration added, but the topic is only minimlly covered in the text, and with no example or discussion of input. The exact wording of the problem is "Rewrite the Menu Chooser program from this chapter using an enumeration to represent difficulty level. The variable choice will still be of type int." I ignored that part as I didn't see the point of enumeration if the input would be an integer anyway, and when I used choice in the enum statement, I added level in an attempt to imitate the weak example in the previous chapter (1) of the book. I'm going to try again from scratch. If this assignment is as complex as the last post suggests, I have no hope of passing the class LOL.

The numeric limits line was one of the instructor provided examples (he calls it the "Dawson Method") to keep the console open. I was using system(pause), which he also offered, until I read the posts on this forum about how bad it is.

I've never worked in a language even remotely close to C++, as you can probably tell, so I have no idea what most of the help even means yet, but thankyou nonetheless.

Here's a redo that runs, but the enumeration sure seems silly...
// Menu Chooser rewrite, p70-1
// Demonstrates the switch statement and enumeration

#include <iostream>

using namespace std;

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

enum level {easy = 1, normal, hard};
int choice;

cout << "Choice: ";
cin >> choice;

switch (choice)
{
case easy:
cout << "You picked Easy." << endl;
break;
case normal:
cout << "You picked Normal." << endl;
break;
case hard:
cout << "You picked Hard." << endl;
break;
default:
cout << "You made an illegal choice." << endl;
}

cout << "Press ENTER to continue...";

system("pause");

return 0;
}


And yes, I know the system("pause") is bad, but the other one he gave us didn't work and I don't want to use something I can't explain when the instructor guesses that I just copied code from the internet. BTW, it was indented before I copy/pasted.
Last edited on
Yes, that would work.
Here, a quick help you to understand it.
Normally en enum type variable represents a value starting from given/default incremented by one. You can set the initial values without a specific increment though.
In your (copied) example, it inputs a number in integer but compares against a numeric value represented by enumerated concstants.

When you give the value 1 for "choice", the same 1 represent by "easy" too but enumerated (just a constant/name, just assume it just as a simple constant/literal), would match the case expression and print out the given cout Easy statement.

Hope this helps.
Good luck ;)
I would just like to add a comment about enums, expanding on what Duoas said.

They are constants representing one of a collection of related items. Yes, they are each a const int behind the scenes but you should never rely on their numeric values. In the abstraction of enums, they rarely have any relation to other enums within the collection in terms of ascending or decending orders, and as such their ordering should never be relied upon

For example

1
2
3
4
5
6
typedef enum FruitEnum
{
    eFRUIT_APPLE,
    eFRUIT_PEAR,
    eFRUIT_BANANA
} EFruit;

in this example eFRUIT_APPLE = 0, eFRUIT_PEAR = 1, and eFRUIT_BANANA = 2, values assigned by the compiler. consider the following code
1
2
3
4
5
EFruit fruit = eFRUIT_APPLE;
if (fruit > eFRUIT_PEAR)
{
   . . .
}

Although testing fruit to be greater than pear is a legal statement because of the underlying numeric values, within the fruit abstraction it makes no sense.

A good rule to follow is that the order of enumerations, and hence their underlying numeric values should be able to be changed without breaking the code.
Last edited on
Brewmaster
That looks fine. system() is evil, but that doesn't mean you should never use it. Here is what the C++FAQ-Lite says about such stuff:
http://www.parashift.com/c++-faq-lite/big-picture.html#faq-6.15

BTW, you'll see "Press enter to continue..." twice the way you have it there...

bnbertha
Careful how you use the word "never". ;-)

all
Frankly, I agree nearly 100% with him. Unfortunately, the C and C++ standards are pretty explicit about which values are mapped to enumerated constants, which sometimes leads programmers to think of them as "#define without using #define".

In C and C++ there is nothing wrong with having enumerated names have specific values. The danger comes when you break the abstraction.

For example, my first extraction operator (on lines 20 through 30) relied upon the specific values of the enum. This is (in C and C++) considered acceptable because the abstraction is not broken: the extraction operator is part of the interface for using the choice enum. That is to say, it is perfectly fine for internal organs to know something about the body.

Where the abstraction breaks is actually on lines 36 through 38. Here, a piece of code external to the choice type knows something about choice's insides. Not only that, but it tells the user the details. (Of course the user doesn't know anything about the enum, but it does highlight some of the issues with this homework assignment. In particular, it shows how using an enum as an int is usually a bad idea...)

:-@
Topic archived. No new replies allowed.