tags:

views:

109

answers:

3

I would like to be able to serialize my C++ classes using standard techniques like std::stringstream or boost::lexical_cast.

For example if I have a Point object (2, 4) then I would like to serialize it to "(2, 4)", and also be able to construct a Point object from this string.

I have some code already but with a few issues. Point to string works, but sometimes the input isn't completely read from the stream. The string to Point conversion results in a bad_cast exception.

class Point
{
public:
    Point() : mX(0), mY(0) {}
    Point(int x, int y) : mX(x), mY(y){}
    int x() const { return mX; }
    int y() const { return mY; }
private:
    int mX, mY;
};

std::istream& operator>>(std::istream& str, Point & outPoint)
{
    std::string text;
    str >> text; // doesn't always read the entire text
    int x(0), y(0);
    sscanf(text.c_str(), "(%d, %d)", &x, &y);
    outPoint = Point(x, y);
    return str;
}

std::ostream& operator<<(std::ostream& str, const Point & inPoint)
{
    str << "(" << inPoint.x() << ", " << inPoint.y() << ")";
    return str;
}

int main()
{   
    Point p(12, 14);    
    std::string ps = boost::lexical_cast<std::string>(p); // "(12, 14)" => OK    
    Point p2 = boost::lexical_cast<Point>(ps); // throws bad_cast exception!
    return 0;
}

How can I fix these problems?

+3  A: 

AFAIK, str >> text; will read a single "word" from the stream.

Parsing is hard. What about something like this (untested):

char paren;
str >> paren;
if (paren != '(') throw ParseError(); // or something...

int x, y;
char comma;
str >> x >> comma >> y;
if (comma != ',') throw ParseError();

str >> paren;
if (paren != ')') throw ParseError();
Nicolás
Yes, the extraction operation is delimited by whitespace.
joshperry
+3  A: 

Since you're already using boost, why don't you look ate boost serialization?

The serialization format should be independent of the objects being serialized, boost's lib handles this well.

joshperry
+5  A: 

To read an entire line, you can use the function std::getline:

std::string text;
getline(str, text);
R Samuel Klatchko
Thanks, this simple changed fixed my code!
StackedCrooked