开发者

Input from stream to enum type

开发者 https://www.devze.com 2023-02-24 05:23 出处:网络
How to input fr开发者_StackOverflow社区om stream to enum type? I can do it so unsigned int sex = 0;

How to input fr开发者_StackOverflow社区om stream to enum type?

I can do it so

unsigned int sex = 0;
stream >> sex;
student.m_bio.sex = static_cast<Sex>(sex);

Otherwise?


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


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

0

精彩评论

暂无评论...
验证码 换一张
取 消