Re: [boost] [lexical_cast] A suggestion

Alexander Nasonov <alnsn <at> yandex.ru> writes:
This looks interesting but boost::optional<T> is already InputStreamable: #include <boost/optional/optional_io.hpp>
This sounded really cool to me so I attempted a cursory hack to get this working. The only way I could figure out how to provide an override for optional<T> that never throws was to change detail::lexical_cast from a function to a struct to get partial template specialization. Maybe there is a better way, I'm new at this. It seems like there must be because I wound up with lots of almost- duplicated code. Here's the old familiar detail::lexical_cast, structified: And here's the optional<T> specialization: Initially this didn't work however. I traced it to what might be a bug in optional_io.hpp's insertion operator: if ( in.good() ) { int d = in.get(); if ( d == ' ' ) /* assuming a space in stream, what if there's not? */ { T x ; in >> x; v = x ; } else v = optional<T>() ; } return in; With the above insertion operator code, this would fail: istringstream si ("test"); optional<string> o; si >> o; assert (o); /* fails, would work if si were constructed with " test" instead */ That seems wrong to my thinking, but maybe there's a reason for the if (d == ' ') test? If the intent was to simply eat up spare white space, how about this instead: if (in) { T x; if (in >> std::ws >> x) v = x; else v = optional<T>(); } return in; Using that code in optional_io.hpp, and with the above changes, things work out just fine: int invalid_as_uint = -1; int valid_as_uint = 5; unsigned default_uint = 6; // Normal form, throws. try { unsigned i = lexical_cast<unsigned> (invalid_as_uint); cout << i << endl; } catch (const bad_lexical_cast&) { cout << "bad lexical cast error" << endl; } // Overload for lexical_cast<optional<T>>, does not throw. optional<unsigned> i = lexical_cast<optional<unsigned> > (invalid_as_uint); if (i) cout << *i << endl; else cout << "invalid return value" << endl; i = lexical_cast<optional<unsigned> > (valid_as_uint); if (i) cout << *i << endl; else cout << "invalid return value" << endl; Also, I would love to see a fallback style lexical_cast for the same reasons Neil already mentioned. -- Andrew Troschinetz
participants (1)
-
Andrew Troschinetz