Angus Comber
Angus Comber

Reputation: 9708

Replacing enum with class with int identifiers - doesn't compile

I am working on a project where we had a standard enum like this:

enum Services {
      RequestShower = 611,
      RequestBath = 617,
      RequestShave = 612,
      RequestHaircut = 618
};

But my boss was saying that the latest C++ standard doesn't regard an enum to be equivalent to an int so instead proposed using a class a bit like this:

class VatelPrivateService {
public:
   static const short
      RequestShower = 611,
      RequestBath = 617,
      RequestShave = 612,
      RequestHaircut = 618;

   static const char* getName(int val);
};

ostream operator<<(ostream& os, VatelPrivateService& service);

Well, I tried to implement like this:

const char* VatelPrivateService::getName(int id)
{
 #define CASE_NM(rq) case rq: return #rq
   switch(id)
   {
      CASE_NM(RequestShower);
      CASE_NM(RequestBath);
      CASE_NM(RequestShave);
      CASE_NM(RequestHaircut);
   }
#undef CASE_NM
   return "";
}

ostream& operator<<(ostream& os, const VatelPrivateService& service)
{
   os << VatelPrivateService::getName(service);
   return os;
}

and call it like this:

cout << "item: " << VatelPrivateService::RequestShower << endl;

But the code above doesn't compile - get : error C2664: 'VatelPrivateService::getName' : cannot convert parameter 1 from 'const VatelPrivateService' to 'int'

Hopefully you can see my intent. how do I fix this?

Angus

Upvotes: 1

Views: 1849

Answers (4)

Mooing Duck
Mooing Duck

Reputation: 66922

Your VatelPrivateService is (effectively) a namespace, not a class, since it has no data. Which means ostream operator<<(ostream& os, VatelPrivateService& service); isn't going to do much, since the service passed to the ostream has no data. Your values are all of type unsigned short, which means you should have had ostream operator<<(ostream& os, unsigned short service);. Except that's already defined. You would need to make VatelPrivateService an actual value-type class, so it holds a value to make this possible.

Of course, the real answer, is your boss is wrong, enums will work as they always have. Don't do any of this.

Upvotes: 3

DeCaf
DeCaf

Reputation: 6096

Your operator overload accepts an instance of VatelPrivateService as an argument, or rather a const reference to one. But the members defined within VatelPrivateService, for example VatelPrivateService::RequestShower that you are passing to cout are of type short, so even if you changed your implementation of the operator<< overload so that it compiled it still would not get called for the VatelPrivateService::RequestShower parameter, since this is just a simple short.

An enum is not equivalent to an int, but is usually implicitly convertible to and from one, and if not you can use static_cast for the conversion. Using the enum is actually the simplest solution that I can think of, and the one that I would use, can if needed cast it to an int where so required.

Upvotes: 1

Ed Heal
Ed Heal

Reputation: 60007

Try

class VatelPrivateSer
{
  private:
    const int value;
    VatelPrivateSer(int value) : value(value) {};
  public:
    static const VatelPrivateSer RequestBath() { return 617; }
    static const VatelPrivateSer RequestHaircut() { return 618; }
    static const VatelPrivateSer RequestShave() { return 612; }
    static const VatelPrivateSer RequestShower() { return 611; }
    int AsInt() const { return value; }
};

You can always use my web page http://well-spun.co.uk/code_templates/enums.php :-)

Upvotes: 0

James McNellis
James McNellis

Reputation: 355069

the latest C++ standard doesn't regard an enum to be equivalent to an int

The specification of enum has not changed: an enumerator is still implicitly convertible to its underlying integral type.

C++11 adds a new concept, enum class, which is a "strongly typed and scoped enum." This new kind of enumeration does not allow its enumerators to be implicitly converted to the underlying integral type (though, you can explicitly coerce the conversion using static_cast).

If you want to write your own scoped enumeration that provides semantics and behavior similar to enum class but is usable on compilers that do not support enum class, you should read Howard Hinnant's answer to this other question, wherein he provides a working example.

Upvotes: 7

Related Questions