如何以通用方式从std :: istream中读取枚举

时间:2012-06-24 12:52:12

标签: c++ templates enums iostream

  

可能重复:
  Input from stream to enum type

我有几个不同枚举的类作为类成员,我想从流中读取类。

以下代码显示了一个示例性类:

  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; 
  };

不幸的是,由于无法直接读取enum值,因此无法使用此功能(没有>>的模板)。

因此我创建了一个帮助类:

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;    
};

现在我可以编写用于阅读MyClass的代码,如下所示:

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;      
}

这已经离我想要的不远了,但仍然需要两个辅助类的间接,这不能写成temporarys:

friend std::istream& operator>>(std::istream& in, MyClass& val) {
 in >>  ScanTo<enSide>(val.mSide)>> ScanTo<enType>(val.mType) >> val.mTargetId;        
 return in;      
}

无法编译(gcc 4.43),因为注释中指出禁止对临时文件进行非const引用。

  

所以问题出现了:

     

如果不依靠上面提到的某些临时工具和模板,这可以更轻松吗?

2 个答案:

答案 0 :(得分:1)

我想你可以写一个帮助函数模板:

template <class T>
std::istream& operator >>(std::istream& is, T& t)
{
    int i;
    is >> i;
    t = (T)i;
    return is;
}

使

in >> val.mSide >> val.mType >> val.mTargetId;

可能的。

答案 1 :(得分:0)

最好的选择是将数据成员定义为int,并使用类型安全访问器来设置和检索它们。

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; 
};

这可以避免你想要的临时工。