Reputation: 9708
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
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
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
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
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