问题
Possible Duplicate:
Input from stream to enum type
I have several classes with different enums as class members and I want to read the classes from a stream.
The following code shows an exemplary class:
enum enSide{
eLeft,
eRight
};
enum enType{
eConUndefined,
eConRoom
};
class MyClass{
public:
friend std::istream& operator>>(std::istream& in, MyClass& val) {
in >> val.mSide >> val.mType >> val.mTargetId;
return in;
}
MyClass(){}
private:
enSide mSide;
enType mType;
int mTargetId;
};
Unfortunately this does not work since direct reading into an enum
Value is not possible (no template for >>).
Thus I created a helper class:
template<class ENUM>
class ScanTo{
public:
friend std::istream& operator>>(std::istream& in, ScanTo<ENUM>& eval) {
unsigned int val;
in >> val;
eval.mrEnum = static_cast<ENUM>(val);
return in;
}
ScanTo(ENUM& eRef):mrEnum(eRef){}
private:
ENUM& mrEnum;
};
Now I can write the code for reading MyClass
as follows:
friend std::istream& operator>>(std::istream& in, MyClass& val) {
ScanTo<enSide> scanside(val.mSide);
ScanTo<enType> scantype(val.mType);
in >> scanside >> scantype >> val.mTargetId;
return in;
}
This is already not far from what I wanted but still needs two indirections over the helper class, which cannot be written as temporarys:
friend std::istream& operator>>(std::istream& in, MyClass& val) {
in >> ScanTo<enSide>(val.mSide)>> ScanTo<enType>(val.mType) >> val.mTargetId;
return in;
}
does not compile (gcc 4.43), because a non const reference to a temporary is forbidden as pointed out in the comments.
So here comes the question:
Can this be done easier without resorting to some temporaries and templates as done above?
回答1:
I think you may write a helper function template:
template <class T>
std::istream& operator >>(std::istream& is, T& t)
{
int i;
is >> i;
t = (T)i;
return is;
}
which makes
in >> val.mSide >> val.mType >> val.mTargetId;
possible.
回答2:
The best option for you is to define your data members as int
, and use type safe accessors to set and retrieve them.
class MyClass{
public:
friend std::istream& operator>>(std::istream& in, MyClass& val) {
in >> val.mSide >> val.mType >> val.mTargetId;
return in;
}
MyClass(){}
enSide side () const { return static_cast<enSide>(mSide); }
void side (enSide v) { mSide = v; }
enType type () const { return static_cast<enType>(mType); }
void type (enType v) { mType = v; }
int targetId () const { return mTargetId; }
void targetId (int v) { mTargetId = v; }
private:
int mSide;
int mType;
int mTargetId;
};
This avoids the temporaries as you desired.
来源:https://stackoverflow.com/questions/11177580/how-to-read-enums-from-a-stdistream-in-a-generic-fashion