从流输入到枚举类型

11

如何从流中输入枚举类型?

我可以这样做

unsigned int sex = 0;
stream >> sex;
student.m_bio.sex = static_cast<Sex>(sex);
否则呢?
3个回答

14
inline std::istream & operator>>(std::istream & str, Sex & v) {
  unsigned int sex = 0;
  if (str >> sex)
    v = static_cast<Sex>(sex);
  return str;
}
如果您想确保该值是有效的,可以这样做:
enum Sex {
    Male,
    Female,
    Sex_COUNT
};

inline std::istream & operator>>(std::istream & str, Sex & v) {
  unsigned int sex = 0;
  if (!(str >> sex))
    return str;
  if (sex >= Sex_COUNT) {
    str.setstate(str.rdstate() | std::ios::failbit);
    return str;
  }
  v = static_cast<Sex>(sex);
  return str;
}

我认为你的意思是 v = static_cast<Sex>(sex); ...也就是说,转换的参数是 sex,而不是 v。 :D - Nawaz
这个答案缺少一个 return str; - Konrad Rudolph
@Konrad Rudolph:谢谢,已经修复了,现在我要去再泡一些咖啡——看来我需要它:P - Erik
很遗憾,枚举类型没有is_valid函数。 - edA-qa mort-ora-y
@edA-qa mort-ora-y:首先,谁在使用is_valid - Nawaz
@Nawaz,这里没有人在使用它,我只是想说有这样一个函数会很好。这样说Sex.is_valid(sex)会非常方便。 - edA-qa mort-ora-y

4

这个问题的一般形式已经在这里提出:如何以通用的方式从std::istream中读取枚举。 原帖的解决方案基本上就差一点点,只是有些麻烦的地方需要处理 const 和一些不必要的尖括号。这里是完整的可行解决方案:

#include <iostream>
#include <type_traits>

enum enSide { eLeft, eRight };
enum enType { eConUndefined, eConRoom };

template<typename Enum>
class EnumReader
{
    Enum& e_;

    friend std::istream& operator>>(std::istream& in, const EnumReader& val) {
      typename std::underlying_type<Enum>::type asInt;
      if (in >> asInt) val.e_ = static_cast<Enum>(asInt);
      return in;
    }
  public:
    EnumReader(Enum& e) : e_(e) {}
};

template<typename Enum>
EnumReader<Enum> read_enum(Enum& e)
{
    return EnumReader<Enum>(e);
}

class MyClass {
    enSide mSide;
    enType mType;
    int mTargetId;
  public:
    friend std::istream& operator>>(std::istream& in, MyClass& val) {
        in >> read_enum(val.mSide) >> read_enum(val.mType) >> val.mTargetId;
        return in;
    }
};
read_enum函数模板在此处的作用与标准库中的std::make_pairstd::make_shared相同:它让我们省略了尖括号。你可以同样地写成in >> EnumReader<enSide>(val.mSide) >> EnumReader<enType>(val.mType),但那样会更加冗长(双关语)。
据称,一些供应商的标准库仍然缺少std::underlying_type,这个头文件在<type_traits>中。如果你使用的是这些不完整的库之一,你可以使用如何知道类枚举底层类型的方法?中列出的其中一种解决方法。

1

这不太好看,但应该能行。

stream >>  reinterpret_cast<std::underlying_type<Sex>::type &>(student.m_bio.sex);

干杯, CC


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接