c++operator-overloadinglexical-cast

bad_lexical_cast exception on overloaded operator ">>"


I've overloaded operator ">>" for an Enum:

#include <iostream>
#include <boost/lexical_cast.hpp>


using namespace std;

enum MyEnum
    {
        ONE = 0,
        TWO, 
        TREE,
        MAX
    };

const char* MyEnumString[MAX] =
{
    "ONE"
    ,"TWO"
    ,"THREE"
};

istream& operator>>(istream& is, MyEnum& myEnum)
{
    string value;
    is >> value;

    myEnum = ONE;

    for (int i=0; i < MAX; i++)
    {
        if (!value.compare(MyEnumString[i]))
        {
            myEnum = static_cast<MyEnum>(i);
            return is;
        }
    }

    return is;
}

int main()
{
   cout << "Hello World" << endl; 
   boost::lexical_cast<MyEnum>(""); //Throws exception. 

   return 0;
}

The output I'm getting:

Hello World terminate called after throwing an instance of 'boost::exception_detail::clone_impl

' what(): bad lexical cast: source type value could not be interpreted as target

The exception is thrown from lexical_cast_39.hpp (1155):

if (interpreter >> result)

The operator is working for every value except empty string. The input stream that being returned from the operator is the same stream that was from the beginning.

What is the acceptable approach for such issue? Thanks!


Solution

  • The issue is that you're telling lexical_cast to convert the empty-string into a MyEnum. What would you expect it to do? It can't return a real value, so an exception is correct.

    A more detailed breakdown: lexical_cast is taking the input empty-string, and creating an input stream from that value. That is then passed to your operator>>. When you do is >> value;, it sets the eof flag on the stream (since it attempted to read the string, and there was no data left.

    After your function returns, it then finishes the if ( interpreter >> result ), which basically checks to see if the stream is still in a good state. Since it is not (due to the eof bit earlier), it fails with an exception.

    If you want an empty string to be interpreted as a specific value, you have to clear the error flags from the stream prior to returning. Personally, I wouldn't do this, since it would limit the usefulness of the input operator in other situations. If I needed this capability, I would most likely end up having a check for the empty-string prior to invoking lexical_cast.