
Roland Richter wrote:
Reece,
I just checked out outfmt from the sandbox CVS and did some tests to see whether it works together with lexical_cast. The general idea is this:
Since lexical_cast internally uses a stringstream and its associated operators>> and <<, it should be possible to cast each type for which these operators are defined; and since outfmt defines <</>> for STL container types, I tried to combine them in order to convert between strings and STL containers.
After some hassle, it works (under MS VC++ 7.0); see the attachment. Issues:
1) For reasons I don't completely understand, the compiler could not find operator<< from stl_io_basic.hpp when compiling lexical_cast.hpp. I had to hack detail/stl_io_basic.hpp and put everything in namespace boost::detail (where lexical_stream lives).
BTW, I'm not happy that stl_io.hpp includes everything from vector to slist, and that so much code is put into the global namespace.
I am aware of this and am working on splitting the code into files like <boost/outfmt/stl/vector.hpp>, etc. There are three main areas that need to be split: [1] The STL I/O code [2] The type identification code [3] The get/put helpers for pair-like objects I have got a version of this to work with MS VC 7.x, but I have a compilation problem on borland and GCC 2.95.3-5 is generating a "signal 13" message on the regression tests (I think this is my cygwin setup, but haven't verified this). I have since been busy and haven't had a chance to look into these. I shall move the inserters and extractors to the boost::detail namespace and will look into the lexical_cast problem.
2) The output operator puts spaces after '[', before ']', and after each ','; whereas the input operator expects no spaces at all; if spaces were present, a bad_lexical_cast exception was thrown. I think it is really important that operator>> can deal with an output which was generated by <<; stated in terms of lexical_cast,
lexical_cast<T>( lexical_cast<string>( t ) ) == t
should hold for any T t.
I stripped and skipped the spaces during the read operation to allow for the read operation to accommodate input variations, e.g. [ a, b ]; [a, b] and [ a,b ] would be read by the same formatter, making it easier to interoperate with data generated from other sources. I could make this a configurable option that does not strip the spaces by default. This should work. If you have examples where it doesn't, please let me know and I can add it into the regression tests. NOTE: There is a known defect when handling string data. This may be generating the problem you are encountering. If you run my regression tests (libs/outfmt/test/generate.sh) you should see it as a fail. I am aware of the problem and am looking into it. (This is made more difficult because the solution I implemented doesn't work with Borland :()
I intend to do some further tests, and to give more feedback during the IO Formatters formal review (no date is fixed yet, or is it?)
Thanks. I appreciate the feedback. I would like to get the string
// Copyright Roland Richter 2004. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/test/minimal.hpp>
#include <vector> #include <string>
#include <iostream>
#include <boost/lexical_cast.hpp> #include <boost/outfmt/stl_io.hpp>
// 1) Namespace problem: // e:\lib\boost_1_31_0\boost\lexical_cast.hpp(144): error C2679: binary '<<' : // no operator found which takes a right-hand operand of type 'const _STL::vector<_Tp,_Alloc>' (or there is no acceptable conversion) // with // [ // _Tp=double, // _Alloc=_STL::allocator<double> // ] // // => move everything in boost/outfmt/detail/stl_io_basic.hpp into namespace boost::detail
// 2) operator<< puts spaces after '[' and ',', whereas operator>> expects // no spaces at all (otherwise, bad_lexical_cast is thrown).
void lexical_cast_and_outfmt_test() { double foos[] = {0.7016, 0.9943, 1.3441, 1.1637, 0.5994, 0.0000, 0.0000}; std::vector<double> fooVec( foos, foos + 7 );
std::string fooStr( "[ 0.7016, 0.9943, 1.3441, 1.1637, 0.5994, 0, 0 ]" );
// Output std::string castedStr = boost::lexical_cast<std::string>( fooVec ); BOOST_CHECK( castedStr == fooStr );
std::string fooStr_WithoutSpaces( "[0.7016,0.9943,1.3441,1.1637,0.5994,0,0]" );
// Input std::vector<double> castedVec = boost::lexical_cast< std::vector<double> >( fooStr_WithoutSpaces ); BOOST_CHECK( castedVec == fooVec ); }
int test_main( int, char *[] ) { lexical_cast_and_outfmt_test();
return 0; }
_________________________________________________________________ Sign-up for a FREE BT Broadband connection today! http://www.msn.co.uk/specials/btbroadband

Reece Dunn wrote:
2) The output operator puts spaces after '[', before ']', and after each ','; whereas the input operator expects no spaces at all; if spaces were present, a bad_lexical_cast exception was thrown. I think it is really important that operator>> can deal with an output which was generated by <<; stated in terms of lexical_cast,
lexical_cast<T>( lexical_cast<string>( t ) ) == t
should hold for any T t.
I stripped and skipped the spaces during the read operation to allow for the read operation to accommodate input variations, e.g. [ a, b ]; [a, b] and [ a,b ] would be read by the same formatter, making it easier to interoperate with data generated from other sources. I could make this a configurable option that does not strip the spaces by default.
It's really good question if the >> operator should be prepared to find a stream which has 'skipws' bit unset. Given that streams usually generate human-readable data, skipping whitespace is a common behaviour, and I'd say that 'noskipws' manipulator should be used only for special circumstances. So, in my opinion lexical_cast<T> should not use 'noskipws', and not force other libraries to manually skip whitespace. - Volodya
participants (2)
-
Reece Dunn
-
Vladimir Prus