Question

I'm starting learning C++ and I cant find the cause of the error below. This code is in the book "Teach Yourself C++ ".

main.cpp:13: error: ambiguous overload for ‘operator>>’ in ‘std::cin >> (int)ip’

#include<iostream>

using namespace std;

enum ignition_parts {distributor=1,cap,points,plug,condenser,coil,wires,done};


 main() {

 ignition_parts ip;
 do{
 cout << "\nInsira no item (1-7, 8 para sair):";
 std::cin >> (int)ip;
 switch(ip){

     case distributor: cout<< "Distribuidor";
     break;

     case cap: cout<< "Tampa";
     break;

     case points: cout << "Pontos";
     break;

     case plug:cout << "Vela";
     break;

     case condenser: cout<<"Condensador";
     break;

     case done: break;

     default: cout << "No item ignorado";
     break;

     }

     } while (ip != done);

}
Était-ce utile?

La solution 2

A suggestion: Use an array for identifier to string conversions.

std::ostream& operator<<(std::ostream& os, ignition_parts ip)
{
    static const char * names[] =
    {
       "Nothing",
       "Distribuidor", "Tampa", "Pontos", "Vela", "Condensador"
    }
    // Test ip for validity first.
    os << names[ip];
}

The above is not safe because if the enum order changes, the mappings in the above table will produce incorrect results. Also, if the enum is expanded and the array isn't, you can get a runtime buffer overrun error (nasty).

A safer method is to include the identifier in the table:

struct Entry
{
    ignition_parts part_id;
    const char *   name;
};
const Entry  name_table[] =
{
  {distributor, "Distribuidor"},
  {cap,         "Tampa"},
  {points,      "Pontos"},
  {plug,        "Vela"},
  {condenser,   "Condensador"},
};
const unsigned number_of_entries =
    sizeof(name_table) / sizeof(name_table[0]);

You search each entry for a matching ID, then return the name field of the table entry.

A good benefit of this method is that you can add entries without changing code and the order is not dependent (order of entries does not matter).

Autres conseils

All overloads are equally bad ;)

    std::cin >> (int&)ip;

Would be "close" Since you cannot assign to an rvalue.

However, do

    int tmp;
    std::cin >> tmp;
    ip = static_cast<ignition_parts>(tmp);

instead for portability/defined behaviour

Here's a version with added error-handling, and extracting the output streaming of ip into it's own function: See it Live on Coliru

#include<iostream>

enum ignition_parts {distributor=1,cap,points,plug,condenser,coil,wires,done};

std::ostream& operator<<(std::ostream& os, ignition_parts ip)
{
    switch(ip) {
            case distributor: return os << "Distribuidor";
            case cap:         return os << "Tampa";
            case points:      return os << "Pontos";
            case plug:        return os << "Vela";
            case condenser:   return os << "Condensador";
            default:          return os << "No item ignorado";
    }
    // unreachable
}

int main() {
    ignition_parts ip;
    do {
        std::cout << "\nInsira no item (1-7, 8 para sair): ";

        int tmp;
        if(std::cin >> tmp) 
        {
            ip = static_cast<ignition_parts>(tmp);

            if (ip == done) {
                break;
            }

            std::cout << ip;
        } else {
            if(std::cin.eof()) {
                break;
            }
            std::cout << "Whoops: invalid input\n";
            std::cin.clear();
            std::cin.ignore(1024, '\n');
        }

    } while(std::cin && ip != done);

}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top