RE: [boost] Re: Formal review of "Output Formatters" library beginstoday

Thorsten Ottosen wrote:
Or "boost/ioformat" since it also has input capabilities :). There was talk when I was developing the library about moving it into the "boost/io" directory, but that seems to be getting a little crowded ;)
It doesn't! This was a typeo. (Fixed in my documents, will commit post-review).
You mean when reading in the input? The default behaviour is to set the input stream fail bit, so you can check that.
3. cryptic name: formatob.hpp && formatobex; should be format_object and whatever the latter really means
I was going for ease of typing :). maybe boost::io::format/boost::io::formatex. The latter allows you to control the delimeter type being used, so you can do: std::wout << boost::io::formatobex< const wchar_t * >( v ).format( " : " );
4. given std::cout << boost::io::formatobex< std::string >( v );
maybe std::string should be a default argument?
I was thinking here about performance. The default type is const char * which should be fairly flexible without providing compy penalties.
You mean from your Boost.Range library? This is something that I am considering, but don't know enough of the library to do this yet.
6. STL IO: It is not obvious how insertion is done? With push_back or by overwriting elements?
The container is cleared and insert is used to insert the elements into the container.
Because the boost::io::range_t class (created by boost::io::range) does not provide input/output functionality. It is a holder for a range [first, second) so that boost::io::formatob can process it. This is if you either specify a std::pair (boost::io::formatob treats this as a 2-ary type and not a range holder) or a (first, last) pair of values (since boost::io::formatob accepts a single object). It could be possible to make boost::io::range return a boost::io::formatob_t type (and thus allow the above), but when I previously used seperate constructs, it interfered with the type/format deduction mechanism.
Yup. This will provide the default formatting ("[ a, b, c ]" in this case). If you need alternate formatting, you need to use boost::io::formatob.
That would make things fairly long-winded. For example: std::pair < std::pair< int, std::vector< char > >, std::list< std::complex< float > >
mct;
std::cout << boost::io::format_object( mct, boost::io::pair_format ( boost::io::pair_format ( boost::io::basic_format(), boost::io::container_format() ), boost::io::container_format( boost::io::nary_format()) ) ); compared to: std::cout << boost::io::formatob( mct, boost::io::pairfmt ( boost::io::pairfmt( boost::io::basicfmt(), boost::io::containerfmt()), boost::io::containerfmt( boost::io::naryfmt()) ) );
Basically, the "_t" types indicate the implementation type of a given construct. For example, the boost::io::formatob function creates an instance of the boost::io::formatob_t class. With regards to names, I am intending on changing FormatTraits to DelimeterTraits and possibly a few others. I am not sure what you mean by concatenation.
Okay, I will bear that in mind. FYI, the above function returns: formatob_t< T, DelimeterType, typename deducer< T, DelimeterType
Great. Regards, Reece _________________________________________________________________ It's fast, it's easy and it's free. Get MSN Messenger today! http://www.msn.co.uk/messenger

"Reece Dunn" <msclrhd@hotmail.com> wrote in message news:BAY24-F40qFXfyY0QUU00057091@hotmail.com... | Thorsten Ottosen wrote: | >Here are some general comments: | >---------------------------------- | > | >0. I think the library should be put in the directory | >"boost/output_format" | >I hate cryptic names. | | Or "boost/ioformat" since it also has input capabilities :). There was talk | when I was developing the library about moving it into the "boost/io" | directory, but that seems to be getting a little crowded ;) anyone will do...but please don't concatenate names. | >2. In this example | > | > int a[] = { 5, 4, 3, 2, 1 }; | > std::cout << boost::io::formatob( boost::io::range( a, a + 5 )); | > std::cin >> boost::io::formatob( boost::io::range( a, a + 5 )); | > // output: [ 5, 4, 3, 2, 1 ] | > | >it might be good to support a range version with the posibility to | > | >1. throw if there is too few elements | >2. default initialize if there is too few elements | | You mean when reading in the input? yes. |The default behaviour is to set the | input stream fail bit, so you can check that. Ok, I guess that goes in hand with the bahavior of the standard library (although I prefer throw by default). could syntax like std::cin >> io::throw_on_error() >> io::formatob( ... ) std::cin >> io::default_init_rest() >> io::formatob( ... ) be supported too.? | >3. cryptic name: formatob.hpp && formatobex; should be format_object and | >whatever the latter really means | | I was going for ease of typing :). maybe | boost::io::format/boost::io::formatex. The latter allows you to control the | delimeter type being used, so you can do: yeah, what does "ex" mean? | I was thinking here about performance. The default type is const char * | which should be fairly flexible without providing compy penalties. seems reasonable...just mention this stuff in the docs. | >5. A lot of boost::io::range() can be replaced with one Taking a Single | >Pass | >Range | | You mean from your Boost.Range library? This is something that I am | considering, but don't know enough of the library to do this yet. Ok, basically you can replace foo( std::pair<iterator,iterator> ); foo( T (&array)[sz] ); foo( const standard_container& ) foo( builtin-strings ); with one function taking a Range foo( const Range& ); | >6. STL IO: It is not obvious how insertion is done? With push_back or by | >overwriting elements? | | The container is cleared and insert is used to insert the elements into the | container. ok, a small comment about it would be good. | >7. why is it necessary with | > boost::io::formatob( boost::io::range( a, a + 5 )); | > could we not just say | > boost::io::range( a, a + 5 ); | | Because the boost::io::range_t class (created by boost::io::range) does not | provide input/output functionality. It is a holder for a range [first, | second) so that boost::io::formatob can process it. This is if you either | specify a std::pair (boost::io::formatob treats this as a 2-ary type and not | a range holder) or a (first, last) pair of values (since boost::io::formatob | accepts a single object). hm...it seems to me that boost.range has all you need: class iterator_range or class sub_range + function make_iterator_range( a, a + 5 ); I could probably benefit you code to use this instead (unless I'm overlooking something). You can look at the range docs in the main cvs in /libs/range/doc | >9. I would prefer basicfmt_t to be basic_format_type or perhaps | >basic_fmt_type | >if the "fmt" shorthand is used consistently etc. That is, all the cryptic | > concatenation should be removed. | | That would make things fairly long-winded. For example: | | std::pair | < | std::pair< int, std::vector< char > >, | std::list< std::complex< float > > | > mct; | | std::cout << boost::io::format_object( mct, | boost::io::pair_format | ( | boost::io::pair_format | ( | boost::io::basic_format(), | boost::io::container_format() | ), | boost::io::container_format( boost::io::nary_format()) | ) | ); | | compared to: | | std::cout << boost::io::formatob( mct, | boost::io::pairfmt | ( | boost::io::pairfmt( boost::io::basicfmt(), | boost::io::containerfmt()), | boost::io::containerfmt( boost::io::naryfmt()) | ) | ); yeah, I know, but at least say pair_fmt instead of pairfmt etc. | I am not sure what you mean by concatenation. the contraction of X_fmt to Xfmt. | Okay, I will bear that in mind. FYI, the above function returns: | formatob_t< T, DelimeterType, typename deducer< T, DelimeterType | >::type::outputter > | ! My rationale for not supplying the return types was to not consume more | space and not confuse readers. Marking them *implementation defined* would | be a good idea. yeah, that would be sufficient. br Thorsten

That would be inconsistent with STL stream behavior. If you want an exception to be thrown, set the steam's exceptions(). Then, when any client code sets the stream's fail bit, automatically an exception will be thrown. Example: std::cin.exceptions(std::ios::failbit); // if an error happens, an exception will be thrown. std::cin >> io::formatob(...);
Quite true! That would make it clearer: container_fmt, pair_frmt, array_fmt... So, I second this ;) Best, John -- John Torjo -- john@torjo.com Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.4.0 - save_dlg - true binding of your data to UI controls! + easily add validation rules (win32gui/examples/smart_dlg)
participants (3)
-
John Torjo
-
Reece Dunn
-
Thorsten Ottosen