2012-06-24 2 views
3

Можно создать дубликат:
Input from stream to enum typeКак читать перечисления из ЗППП :: IStream в общем виде

У меня есть несколько классов с различными перечислениями в качестве членов класса, и я хочу, чтобы прочитать классы из потока. не

Следующий код показывает примерный класс:

enum enSide{ 
    eLeft, 
    eRight 
    }; 

    enum enType{ 
    eConUndefined, 
    eConRoom  
    }; 

    class MyClass{ 
    public: 
     friend std::istream& operator>>(std::istream& in, MyClass& val) { 
     in >> val.mSide >> val.mType >> val.mTargetId;   
     return in;  
     } 

     MyClass(){} 

    private: 
     enSide mSide; 
     enType mType; 
     int mTargetId; 
    }; 

К сожалению, это не работает, так как прямое чтение в enum значение не возможно (не шаблон для >>).

Таким образом, я создал вспомогательный класс:

template<class ENUM> 
class ScanTo{ 
    public: 
    friend std::istream& operator>>(std::istream& in, ScanTo<ENUM>& eval) { 
     unsigned int val; 
     in >> val; 
     eval.mrEnum = static_cast<ENUM>(val); 
     return in;  
    } 

    ScanTo(ENUM& eRef):mrEnum(eRef){} 

    private: 
    ENUM& mrEnum;  
}; 

Теперь я могу написать код для чтения MyClass следующим образом:

friend std::istream& operator>>(std::istream& in, MyClass& val) { 
    ScanTo<enSide> scanside(val.mSide); 
    ScanTo<enType> scantype(val.mType); 
    in >> scanside >> scantype >> val.mTargetId;   
    return in;  
} 

Это уже не далеко от того, что я хотел, но все еще нуждается две ссылки на вспомогательный класс, которые не могут быть записаны как временные:

friend std::istream& operator>>(std::istream& in, MyClass& val) { 
in >> ScanTo<enSide>(val.mSide)>> ScanTo<enType>(val.mType) >> val.mTargetId;   
return in;  
} 

не скомпилирует (gcc 4.43), так как ссылка не указана во временном запрете, как указано в комментариях.

Так вот возникает вопрос:

Может ли это быть сделано проще, не прибегая к некоторым временным и шаблонам, как это сделано выше?

+0

Вы видели это? http://stackoverflow.com/questions/5633784/input-from-stream-to-enum-type – kol

+1

Конденсированная версия компилирует (и работает) отлично с моим VS2010. Какой компилятор вы используете? –

+1

@dionadar Я думаю, что VS позволяет привязывать временные файлы ('ScanTo (val.mSide)') к ссылке на не-const ('myClass & val') с помощью расширения. Однако это нестандартно. – jrok

ответ

1

Я думаю, вы можете написать шаблон вспомогательную функцию:

template <class T> 
std::istream& operator >>(std::istream& is, T& t) 
{ 
    int i; 
    is >> i; 
    t = (T)i; 
    return is; 
} 

, что делает

in >> val.mSide >> val.mType >> val.mTargetId; 

возможно.

+1

Это убивает вас, поскольку может быть запущено для любого произвольного типа. Если вы забыли определить оператор >> для своего пользовательского типа, но использовать его в любом случае. Ваш код будет компилироваться, но typecast int для любого настраиваемого типа – Martin

0

Лучшим вариантом для вас является определение ваших данных как int и использование безопасных аксессуаров типа type для их набора и извлечения.

class MyClass{ 
    public: 
    friend std::istream& operator>>(std::istream& in, MyClass& val) { 
     in >> val.mSide >> val.mType >> val.mTargetId;   
     return in;  
    } 

    MyClass(){} 

    enSide side() const { return static_cast<enSide>(mSide); } 
    void side (enSide v) { mSide = v; } 

    enType type() const { return static_cast<enType>(mType); } 
    void type (enType v) { mType = v; } 

    int targetId() const { return mTargetId; } 
    void targetId (int v) { mTargetId = v; } 

    private: 
    int mSide; 
    int mType; 
    int mTargetId; 
}; 

Это позволяет избежать временных затрат по вашему желанию.

Смежные вопросы