C++ Using classes with boost::lexical_cast

Kia.celever picture Kia.celever · Apr 30, 2012 · Viewed 10k times · Source

I want to use my Test class with boost::lexical_cast. I have overloaded operator<< and operator>> but It gives me runtime error.
Here is my code:

#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace std;

class Test {
    int a, b;
public:
    Test() { }
    Test(const Test &test) {
        a = test.a;
        b = test.b;
    }
    ~Test() { }

    void print() {
        cout << "A = " << a << endl;
        cout << "B = " << b << endl;
    }

    friend istream& operator>> (istream &input, Test &test) {
        input >> test.a >> test.b;
        return input;
    }

    friend ostream& operator<< (ostream &output, const Test &test) {
        output << test.a << test.b;
        return output;
    }
};

int main() {
    try {
        Test test = boost::lexical_cast<Test>("10 2");
    } catch(std::exception &e) {
        cout << e.what() << endl;
    }
    return 0;
}

Output:

bad lexical cast: source type value could not be interpreted as target

Btw I'm using Visual Studio 2010 But I've tried Fedora 16 with g++ and got the same result!

Answer

Luc Touraille picture Luc Touraille · Apr 30, 2012

Your problem comes from the fact that boost::lexical_cast does not ignore whitespaces in the input (it unsets the skipws flag of the input stream).

The solution is to either set the flag yourself in your extraction operator, or just skip one character. Indeed, the extraction operator should mirror the insertion operator: since you explicitely put a space when outputting a Test instance, you should explicitely read the space when extracting an instance.

This thread discusses the subject, and the recommended solution is to do the following:

friend std::istream& operator>>(std::istream &input, Test &test)
{
    input >> test.a;
    if((input.flags() & std::ios_base::skipws) == 0)
    {
        char whitespace;
        input >> whitespace;
    }
    return input >> test.b;
}