Boost logo

Boost :

From: Jason House (jhouse_at_[hidden])
Date: 2003-02-25 12:10:03

Terje Slettebø wrote:
> >From: "Jason House" <jhouse_at_[hidden]>
> > Terje Slettebø wrote:
> > > In a way, something good came from it, as well: I've recently looked at
> > > Boost.Tuple, and I see that they have I/O operators defined (in
> > > tuple_io.hpp).
> >
> > Well, it definitely seems like the tuples were thinking along similar
> > lines with a start, middle, and stop delimiters.
> > The documentation brings up a point about parseability of data streams.
> > It doesn't quite make sense to me that there should be restriction to a
> > single character in order to to make things uniquely parseable. If it's
> > a fixed sequence of characters, I don't see how that makes it any
> > significantly less parseable... Maybe I'm missing something?
> The docs says:
> "Note that extracting tuples with std::string or C-style string elements
> does not generally work, since the streamed tuple representation may not be
> unambiguously parseable."
> It's not about the delimiters. which it seems you mean, but about the tuple
> elements. Consider:
> tuple<std::string,int> test;
> stream >> test; // Stream contains "a string, with comma, 123"
> Here, it can't know that the first comma is part of the string, and not
> meant to separate elements. Not to mention that it would stop after "a", due
> to the space character.

you're right... I was thinking that they were referring to the
delimiters not being strings (and forced to be just characters). If the

> I agree that it should be possible to have multi-character delimiters,
> without creating parsing problems. It could be an idea to keep this, as it
> may make for more flexible output. Even single-character delimiters is quite
> flexible, as you can even get each element on its own line, by using '\n' as
> the element separator. To look again at one example of how the tuple way
> might work:
> std::vector<std::pair<char,int> > test;
> std::cout << test: // Using defaults
> (('A',1),('B',2),('C',3))

I would suspect that chars don't get output with '' around them...
Is there even a way to specify/change that? Something similar for
strings (along with an escape character) would be very handy for
strings. Inside C++ code, a start and stop character of " and an escape
of \ is used... I am not familiar with what serialization code is
available, but I would suspect there might be a feature like that
already in there somewhere.

> In this case, it's not possible to set the format for each type separately.
> Maybe it could be good to keep that feature of the current composite
> operators, as well, something like:
> typedef std::pair<char,int> map;
> typedef std::vector<Map> map_list;
> map_list test;
> std::cout << io::set_delimiter<map>("\n") << test;
> Output:
> (('A',1)
> ('B',2)
> (C,3))

so basically, you would like to combine tuple-like output specification
(ie for all tuples) and type specific such as composite_format?

> You might also have a non-template overload of the manipulators, which sets
> the delimiters for all types, as done in tuples.
> This may also have a positive effect on a serialisation library: The
> standard types will have default stream operators.
> > It does enable defaults and allows a way to customize each spacer
> > individually, which is a good addition. I think the ability to set all
> > 3 also is a must-have :)
> Yeah, I think that's useful, too. :)
> > The tuple functions, as provided should be extremely easy to call from a
> > debugger since there is no templating going on.
> Actually, there is. They are defined in tuple_io.hpp as:
> template<class CharType, class CharTrait, class T1, class T2>
> inline std::basic_ostream<CharType, CharTrait>&
> operator<<(std::basic_ostream<CharType, CharTrait>& o,
> const cons<T1, T2>& t)
> As you say, this may be a problem to call from a debugger, unless it
> supports calling function templates. If one need to call it from a debugger,
> one could always wrap the code in a function.

Debugger friendly manipulation would be good. I still haven't thought
about how exactly outputting of an arbitrary composite variable will
work in the debugger by default... I agree that having a wrapper makes
it easy for the output formatting of general types, but actually being
able to execute "std::cout << my_suspect_variable" in the debugger
without premeditation still poses a significant problem. Why can't bugs
be predicted before you notice them?

> There was a suggestion for allowing generic formats, though, using
> the same format for all instantiations of a template. The question is how to
> do it. The current version stores the format for each specific type, as you
> say. Volodya suggested a couple of ways it could be done, partial
> specialisation, or storing the template name in a map. However, it could be
> hard to use the latter, as it could be hard to find the right type to look
> up, when outputting, given that you have specific types, not templates.
> Overloading of class templates might have helped, here. E.g.:
> std::cout << io::set_format<std::vector<std::pair<char,int> >(...); // Set
> specific format (io::format is a class template)
> std::cout << io::set_format<std::vector>(...); // Set generic format for
> std::vector (io::format overloaded with a version taking template template
> parameter, and specialised for std::vector)

Well, <std::vector> would cause trouble because the std::vector requires
extra arguments... I don't think you could get that to compile. Using
a string might work... but using it as a template argument would
probably cause trouble. I don't know if there is a way to use partial
template specialization. There was a recent post about converting type
names to strings... something like that could be a solution... I don't
like having to specify a name for each type necessarily though...

Boost list run by bdawes at, gregod at, cpdaniel at, john at