0

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

Angus Comber
  • 9,316
  • 14
  • 59
  • 107

4 Answers4

6

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.

Community
  • 1
  • 1
James McNellis
  • 348,265
  • 75
  • 913
  • 977
3

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.

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
1

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.

DeCaf
  • 6,026
  • 1
  • 29
  • 51
0

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 :-)

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
  • I probably would have overloaded `operator int()` since they seem to want `enums` to be "equivalent" to ints. – Mooing Duck Oct 21 '11 at 18:09
  • Also make the "values" `static const VatelPrivateSer` (not functions) so you don't need the parenthesis. – Mooing Duck Oct 21 '11 at 18:09
  • Scott Meyers (2nd edition Effective C++) - item 46 is where the template came from. – Ed Heal Oct 21 '11 at 19:14
  • I can understand why Scott Meyers would recommend against `operator int()`, except that the OP implies he would like that functionality in this case. Does Scott Meyers justify why the "values" are functions rather than static objects? Probably so you usually get an error if you try to take the address? – Mooing Duck Oct 21 '11 at 19:15