Этот вопрос был задан в более общей форме: Как читать перечисления из 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>
.Если у вас есть одна из этих неполных библиотек, вы можете использовать один из обходных путей, перечисленных в Как узнать базовый тип перечисления класса? .