Ввод из потока в тип enum - PullRequest
       5

Ввод из потока в тип enum

8 голосов
/ 12 апреля 2011

Как ввести из потока в тип enum?

Я могу сделать это так

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

В противном случае

Ответы [ 3 ]

13 голосов
/ 12 апреля 2011
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;
}
3 голосов
/ 26 января 2014

Этот вопрос был задан в более общей форме: Как читать перечисления из 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_pair или std::make_shared в стандартной библиотеке: он позволяет нам обходиться без угловых скобок.С таким же успехом можно было бы написать in >> EnumReader<enSide>(val.mSide) >> EnumReader<enType>(val.mType), но это более типично (каламбур).

В стандартных библиотеках нескольких поставщиков, как утверждается, до сих пор отсутствует std::underlying_type в заголовках <type_traits>.Если у вас есть одна из этих неполных библиотек, вы можете использовать один из обходных путей, перечисленных в Как узнать базовый тип перечисления класса? .

0 голосов
/ 06 июня 2017

Это не красиво, но стоит это сделать

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

Ура, CC

...