Input from stream to enum type

浪尽此生 提交于 2019-11-29 13:34:17
inline std::istream & operator>>(std::istream & str, Sex & v) {
  unsigned int sex = 0;
  if (str >> sex)
    v = static_cast<Sex>(sex);
  return str;
}

If you want to ensure that the value is valid, you can do something like this:

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

This question was asked in a more general form over here: How to read enums from a std::istream in a generic fashion. The OP almost had a working solution as it was; he just had some trouble with const, and a few unnecessary angle-brackets. Here's the working solution fleshed out:

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

The read_enum function template serves the same purpose here as std::make_pair or std::make_shared in the standard library: it lets us dispense with the angle brackets. You could equally well write in >> EnumReader<enSide>(val.mSide) >> EnumReader<enType>(val.mType), but that's more typing (pun intended).

A few vendors' standard libraries are allegedly still missing std::underlying_type from their <type_traits> headers. If you have one of these incomplete libraries, you can use one of the workarounds listed at How to know underlying type of class enum?.

This is not pretty but should do it

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

Cheers, CC

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!