2

I have the following enum and input stream operator:

enum class MsrEncryptionStatus : unsigned char
{
   Unknown = 0xFF,
   None = 0,
   Ksn,
   Dukpt,
   Other
};

inline std::istream& operator>>(std::istream& s, MsrEncryptionStatus& status)
{
   return s >> static_cast<unsigned&>(status);
}

The above implementation of operator>> does not compile because of the way I'm doing the cast. Clang complains:

main.cpp:34:16: error: non-const lvalue reference to type 'unsigned int' cannot bind to a value of unrelated type 'MsrEncryptionStatus'
   return s >> static_cast<unsigned&>(status);
               ^                      ~~~~~~

What I'm trying to do is avoid defining a variable to temporarily hold the value from the input stream and then static_cast it later. Can someone help me understand what I'm missing here? I feel like I'm missing a fundamental piece of how static_cast functions on lvalues, for example it feels like a temporary is being created here and if that were true I can't bind it to a non-const lvalue reference.

3
  • Why don't you define an operator>> on your enum class instead? Commented Jul 19, 2016 at 21:36
  • What's exactly wrong with using a temporary? Commented Jul 19, 2016 at 22:05
  • Also I wonder if you could make something crazy like: template <typename E> inline typename std::enable_if<std::is_enum<E>::value, std::istream &>::type operator>>(std::istream &s, E &e) { typename std::underlying_type<E>::type tmp; s >> tmp; e = static_cast<E>(tmp); return s; } Commented Jul 19, 2016 at 22:12

2 Answers 2

2

My compiler also refused to do a static cast, but a temp variable is better anyway, due to your other obligations.

You need to read the value, validate it against MsrEncryptionStatus, then either assign it to status, or set the failbit.

Here's the recommended template from cppreference

std::istream& operator>>(std::istream& is, T& obj)
{
    // read obj from stream
    if( /* T could not be constructed */ )
        is.setstate(std::ios::failbit);
    return is;
}
Sign up to request clarification or add additional context in comments.

Comments

1

There is no safe conversion from MsrEncryptionStatus to unsigned int&. That's the reason why static_cast fails. You can use reinterpret_cast if you are completely sure of what you are doing.

In next the next example I show you how dangerous reinterpret_cast is:

int main( )
{
    std::ifstream i( "input.dat" ) ;
    unsigned a ;
    unsigned char b ;
    i >> a ;
    i >> reinterpret_cast<unsigned&>(b) ; // What was I thinking when I wrote this?
    std::cout << a << " " << b << std::endl ;
    return 0 ;
}

If the content of input.dat is:

1234 5678

The result will be something like:

22 .

Which proves you've overwritten the stack.

2 Comments

It actually won't let you cast it to the right type, either. There's more than just that.
@KennyOstrom My mistake! Thanks. If there is another problem I'm not seeing, please let me know. I just wanted to show he could use reinterpret_cast if the input stream was already validated and if the memory referenced by "status" is big enough.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.