Re: [boost] Re: io operations for stl containers?

2003-03-28 Thread Terje Slettebø
>From: "Jason House" <[EMAIL PROTECTED]>

> Terje Slettebø wrote:
> >
> > >From: "Jason House" <[EMAIL PROTECTED]>
> >
> > > 1. Is it at all useful/possible to use a lambda-like notation?
> >
> Thinking about it more, I don't know how doable it is for the first 3
> parameters...
>
> But what about:
>
> /* brain dead function to serve as example */
> std::string printable(char z) {return z=0?"\0":std::string(z);}
>
> char x[7] = "foobar";
> std::cout
><< io_format("{", "}", ", ", "'" << printable(_1) << "'")
><< "x = " << x;
>
> output:
> x = {'f', 'o', 'o', 'b', 'a', 'r', '\0'}
>
> alternates like (printable(_1) or just "'" << _1 << "'" would also work.
>
> That makes the visitor possible, but also makes the inspiring case for
> the extra inputs to io_format be a little more readable...

This still wouldn't, in itself, support things like outputting indices,
though, unless the entity being passed may hold state, such as a function
object.

It also looks like quite a bit more complex, apparently much of it just to
be able to write "\'" << _1 << "\'" instead of "\'","\'".

There's another issue: The type of the lambda expression would likely encode
the expression, meaning you have an issue of how to store and retrieve it,
unless you know the exact type of the object to retrieve.

This is the code to retrieve the format_data object for a given type (given
with "index"):

template
static format_data &format(std::basic_ostream
&stream)
{
  void *&void_ptr=stream.pword(index);

  if(!void_ptr)
void_ptr=new format_data(default_data);

  return *static_cast *>(void_ptr);
}

How to do that, if the object being retrieved is an arbitrary type?


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: io operations for stl containers?

2003-03-27 Thread Terje Slettebø
>From: "Jason House" <[EMAIL PROTECTED]>

> I had 2 thoughts today...
>
> 1. Is it at all useful/possible to use a lambda-like notation?

In what way? Could you have given a rough syntax-example?

An example in BLL is:

std::for_each(v.begin(), v.end(), std::cout << _1 << '\n');

>In the past, I've liked the look of that a lot.
>(the comments about alternate notation made me think of it)
>
> 2. Why are we restricting the output to strings?

That _is_ a natural question, isn't it? :)

>Couldn't the types of the 3 delimiter strings actually be
>implicit template parameters?
>(the char/wchar versions made me think of that)

Yes, that is how it currently works; it deduces the types passed to the
format function template, and returns an object of type format_type
(analogous to many cases, such as bind1st/binder1st).

Since all the string parameters have default to empty string, this is done
by having three overloads of the format function template - for
std::basic_string, const char * and const wchar_t *. That way, you can use
"", L"", etc. as appropriate, for the default.

As mentioned in some previous postings, a possibility for generalising the
formatting could be to pass a "visitor" object to the format-function,
instead of the strings, which is then invoked at the specific times during
output (begin/end sequence, etc.). One could then also support things like
line numbers and indentation, without hardcoding how this is done. It would
also be possible to make a visitor object which took strings in the
constructor, and gave the current semantics.

This approach seems to require dynamical allocation of the format data, and
virtual functions, though. Since this means quite a bit of change, I haven't
done it so far, but I'm open to the possibility.

An example of its use:

// Line numbering visitor (could be included in the library)
//
// All virtual functions are included for illustration. In practice, the
once with empty body could be omitted.

template
class numbering_type : public visitor_base
{
public:
  explicit numbering(int ln) : line_number(ln) {}

  virtual void start_sequence(std::basic_ostream
&stream) {}
  virtual void end_sequence(std::basic_ostream &stream)
{}
  virtual void element(std::basic_ostream &stream,
const T &element)
{ stream << line_number << ' ' << element << '\n'; ++line_number; }

private:
  int line_number;
};

// The numbering function template returns a numbering_type object

typedef std::vector vector;

vector v;

// Fill vector

std::cout << format(numbering())
  << v;

Output:

1 - A
2 - B
3 - C

etc.

Thanks.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


RE: [boost] Re: io operations for stl containers?

2003-03-26 Thread Rozental, Gennadiy
> > I am afraid boost/io/format will be confusing in a sight of 
> presence of
> > Boost.Format.
> 
> I understand. Well, it's in a different namespace.

I do not know why BTW. But even if it stays this way, I easily see a newbie
looking for Boost.Format staff in your headers and vise-vesa

 
> The directories follow the namespaces, so it has "std" and 
> "boost". STL is
> only a subset of the standard library, so also for that 
> reason, I think
> "std" would be more appropriate.

OK.
 
> This should be quite easy to add. The latter style is also 
> used in Reece
> Dunn's list manipulator, which also deals with output for sequences.

That would be great.
 
> I don't have that much practice with it, but I've found 
> myself that I don't
> have a problem remembering which parameter is what, in the 
> 3+2 optional
> parameter list. Lack of verbosity may be considered one of 
> the advantages
> over writing explicit output code.

That is not the problem for the developer - when you actively working with
library. But may be an issue for maintainer. Even if it's the same person.
Let say you returns to the application written year ago and never used this
formatting library meanwhile. Then I am afraid format("","","") could
be a bit confusing.

Gennadiy.
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: io operations for stl containers?

2003-03-26 Thread Terje Slettebø
>From: "Rozental, Gennadiy" <[EMAIL PROTECTED]>

> > #include 
> > #include 
> > #include 
>
> I am afraid boost/io/format will be confusing in a sight of presence of
> Boost.Format.

I understand. Well, it's in a different namespace.

> I would prefer (since it all about container output formatting)
>
> boost/io/container

Well, it actually may handle any composite type, such as std::complex,
std::pair, etc., as well. It also handles any sequence (using
io::sequence(begin,end) ), not just containers.

I used to call it "composite_format", but that was rather long... Using
"io::format(...)", I think is quite succinct.

> Also it could be stl instead of std, though it's the matter of taste.

The directories follow the namespaces, so it has "std" and "boost". STL is
only a subset of the standard library, so also for that reason, I think
"std" would be more appropriate.

> > std::cout << format("[", "]\n", " => ")
> > << format("","","")
> > << values;
>
> ...
>
> > Syntax
> > --
> > format(, , , [ > element>, ])[.set_default_format()]
> > format()
>
> I personally would really prefer verbose format specification. So I should
> not remember what each of the parameters means by it's position.
> Something along this lines:
>
> std::cout << start_elelment( "[" ) // if you need value
> type_here. I am not sure

Yes, you do, or it won't know which type to set it for.

>   << end_element( "]\n" )
>   << element_delimeter( " => " )
>   ...
>   << values;
>
> Or
>
> std::cout << format().start_elelment( "[" ).end_element( "]\n"
> ).delimeter( " => " )
>   ...
>   << values;
>
> Or mix of this styles. Or - the very best - all of them.

This should be quite easy to add. The latter style is also used in Reece
Dunn's list manipulator, which also deals with output for sequences.

I don't have that much practice with it, but I've found myself that I don't
have a problem remembering which parameter is what, in the 3+2 optional
parameter list. Lack of verbosity may be considered one of the advantages
over writing explicit output code.

Thanks for the feedback.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


RE: [boost] Re: io operations for stl containers?

2003-03-26 Thread Rozental, Gennadiy
> #include 
> #include 
> #include 

I am afraid boost/io/format will be confusing in a sight of presence of
Boost.Format.
I would prefer (since it all about container output formatting)

boost/io/container

Also it could be stl instead of std, though it's the matter of taste.

> std::cout << format("[", "]\n", " => ")
> << format("","","")
> << values;

...

> Syntax
> --
> format(, , , [ element>, ])[.set_default_format()]
> format()

I personally would really prefer verbose format specification. So I should
not remember what each of the parameters means by it's position.
Something along this lines:

std::cout << start_elelment( "[" ) // if you need value
type_here. I am not sure
  << end_element( "]\n" )
  << element_delimeter( " => " )
  ...
  << values;

Or

std::cout << format().start_elelment( "[" ).end_element( "]\n"
).delimeter( " => " )
  ...
  << values;

Or mix of this styles. Or - the very best - all of them.

Gennadiy.
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: io operations for stl containers?

2003-03-26 Thread Terje Slettebø
Hi.

I've now uploaded the latest version of the composite stream operators
library at Yahoo Files
(http://groups.yahoo.com/group/boost/files/composite_stream_operators/) and
the Sandbox (boost/io/format/ and libs/io/format)..

Since the libraries in the Sandbox use the boost namespace, this one does
the same. All components are in the boost::io namespace.

There are no docs, yet, but there are several test programs, illustrating
use for all supported types (the list of these are given below). I also
include information here.

Feedback is welcome.

Examples of use:

std::vector
---
#include 

std::vector v;

// Fill vector

// Output (using user-changeable default format)

std::cout << v;

Output:

[1,2,3,4,5,6,7,8,9,10]

std::map

#include 

typedef std::map map;
typedef map::value_type value_type;

map values;

// Fill map

std::cout << format("[", "]\n", " => ")
<< format("","","")
<< values;

Output:

[1 => A]
[2 => B]
[3 => C]

Array
---
#include 

int array[]={1,2,3,4,5,6,7,8,9,10};

std::cout << array << '\n'
<< format<_ (&)[N]>("", "", "\n")
   << array;

Output:

[1,2,3,4,5,6,7,8,9,10]

1
2
3
4
5
6
7
8
9
10

Here is a synopsis
--

namespace boost::io
-

format - Set output formatting
==

Type options
--
"_" - Any type
"N" - Any size (for array)
template_name<_> - Any instantiation of the given template (may need more
"_"s, one for each parameter without default)

Syntax
--
format(, , , [, ])[.set_default_format()]
format()

If set_default_format() is used, it may be used without a stream, and it
then sets the format for all streams.

Examples
--
stream << format >(...) // Set format for std::vector
stream << format >(...) // Set format for any instantiation
of std::vector
stream << format<_>(...) // Set format for any type

stream << format >(false) // Unsets format for
std::vector

It checks for format settings, going from the most specific to the most
general, stopping when it has found a set format. E.g. for the above
example, this means checking in the following order:

std::vector
std::vector<_>
_
_ (any stream)

The library sets the following default for all streams (the last format
checked), which may be changed by the user. This default is set rather
arbitrarily, and is open to change. This is so that no formatting is needed
to be set, to get useful output:

format<_>("[", "]", ",").set_default_format() - Sets format for all types,
for all streams.

It also handles wide character formatting:

format(L"[", L"]", L",")

sequence - Lets a sequence, given with start/end iterators, be output as the
given type
==

Syntax
--
sequence(, )

Examples
--
#include 

std::vector v;

// Fill vector

std::cout << sequence<_>(v.begin(),v.begin()+10);

Output:

[1,2,3,4,5,6,7,8,9,10]


typedef std::istream_iterator in;

std::cout << sequence<_>(in(std::cin),in());

Input:

1 2 3 4 5 6 7 8 9 10

Output:

[1,2,3,4,5,6,7,8,9,10]

wrap - Lets a type be output using set format, even if it has its own output
operator
==

Some types, such as std::complex, std::bitset, and boost::dynamic_bitset
have already output stream operators defined, so to set their format, one
may wrap the value before outputting.

Syntax
-
wrap()

Examples
--
#include 

std::complex value(1.23, 2.34);

std::cout << value << '\n'
<< wrap(value);

Output:

(1.23,2.34)
[1.23,2.34]

Supported types
=
Arrays

std

pair
complex (has output operator, use wrap)
vector
list
deque
set
multiset
map
multimap
bitset (has output operator, use wrap)

boost

dynamic_bitset (has output operator, use wrap)

The supported types may also be extended by the user.

Header organisation

boost/io/format ---
   |--- std
   |--- boost

libs/format/io  ---
|--- tests

Compatibility
==
The library uses standard C++, but isn't very portable currently. It has
been tested on Intel C++ 7.0 and g++ 3.2.

I plan to work on the portability, and should soon get it to work on MSVC,
etc., as well.

The names, syntax and semantics is open to suggestions for change.

I hope Daryle Walker doesn't mind that this library is sharing the "io"
directory and namespace, at the Sandbox. If so, I could change it from
"io/format" to "io_format".

Thanks for the patience to those who have waited for this update.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: io operations for stl containers?

2003-03-17 Thread Terje Slettebø
>From: "Jason House" <[EMAIL PROTECTED]>

> Terje Slettebø wrote:
> > typedef std::vector vector_char;
> >
> > vector_char values;
> >
> > // Fill with 'A', 'B', 'C'
> >
> > std::cout << io::format("[", "]", ", ", "\'", "\'") <<
values;
> >
> > Output:
> >
> > ['A', 'B', 'C']
> >
> > However, is this overkill?
>
>  It seems that way, especially considering that if it was a vector of
> anything other than a fundamental type with std::cout << already defined
> for it, you could add a second io::format("\'","\'","") and it
> would work.

Right. However, I've already implemented it, anyway, as an experimental
feature. :) Besides, the two extra strings default to empty strings.

> > Feedback is most welcome.
>
>   Would possibly a function object for outputting the contained item be
> better?

[I first thought you meant a function object for outputting the _container_,
not the elements, so I wrote the following section, before realising that
you had meant for the elements. I address it afterwards]

I've been thinking of the same, with regard to outputting the _container_
(not the element, itself). In an earlier posting, I mentioned the
possibility of using function objects, as a way to generalising the handling
of output. I also mentioned having the kind of function objects like BGL,
i.e. "visitors". That is, rather than only overloading the operator(), it
may provide several member functions, e.g.:

class stream_visitor
{
public:
  void start();
  void end();
  void delimiter();
};

std::cout << format(stream_visitor(...));

One could then provide a function object which does what it currently does.

There are issues with this, however. I've been thinking long and hard about
how to provide this functionality. The issue is that the functors has to be
stored somewhere, and being accessible. With the current version, all the
format objects are the same type, so you know its type when it's stored and
retrieved. However, if arbitrary (generic) functors are stored, you don't
know its type, when you access it, when performing output. It's similar to
trying to store different types in the same std::vector.

There are solutions to this, and one is to use a common interface, and all
functors inherit from that interface, and override the virtual functions.
That would let you store them using a pointer to the interface. However,
this means the overhead of a virtual function call per call to the member
functions above. This may not be that much, but it's still also the issue
that generic functors can't be used - they all have to inherit from the same
interface.

For this reason, I found that this could be a possible later addition, if we
find that the added flexibility is worth it.

Also, the current syntax could still be kept as a convenience, by having an
overloaded constructor taking the strings, and creating the functor. So a
change may be backwards compatible.

> Here's a possibly mutilated example (I've never actually used
> function objects before):
>
> std::ostream delimitted_char(std::ostream out, char x, std::string
> first, std::string last);
>
> std::cout << io::format("[", "]", ", ",
>   bind("\'", 4, bind("\'", 3, delimitted_char)))

Yes, it's possible, but I this seems to make it more complex than simply
using io::format("[", "]", ",", "\'", "\'"), with the two last
strings defaulted to empty strings.

> > There's yet another alternative way this may be done, using
"placeholder"
> > types, i.e.:
> >
> > std::cout << io::format >(...); // Sets the format for
all
> > vectors
> > std::cout << io::format<_>(...); // Sets the format for all types
(defaults)
> >
> > This would avoid hardcoding any defaults, as the user could change it.
> >
> > The output routines could then check the formats in the following order,
> > e.g. for "std::vector":
> >
> > If there's a format set for std::vector, use it, else
> > if there's a format set for std::vector<_> (all vectors), use it, else
> > use format for _.
> >
> > Comments?
>
> I like it :)

I found it quite neat, as well. :) Interestingly, one important contribution
of libraries are concepts and idioms. Since "_" is used as placeholder other
places, making it mean "any type" here is reasonably intuitive, as well.

> Using just _ scares me a bit... It would have to have a good default :)

Well, it doesn't matter that much, as all the formats are user-settable. The
library may provide a setting for _, but it can easily be set to something
else by the user, in the same way.

In fact, the current version in the Files (the first upload), has as
"defaults" that all strings are empty. So the defaults have existed from the
beginning, anyway. After all, you have to use _some_ format to print types
for which no explicit format has been set. Being able to set this default
explicitly, rather than hardcoding it in the library, should therefore be a
good thing.

In fact, I've made an implementation of the above, yesterday, and I'll just
make some more tests, and upload it to the Files

Re: [boost] Re: io operations for stl containers?

2003-03-16 Thread Terje Slettebø
>From: "Jason House" <[EMAIL PROTECTED]>

> Terje Slettebø wrote:
> >
> > std::vector > 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.

I've found a way this may be done. If you specify "start element" and "end
element" strings, in addition, it may be done. Currently, it takes "start
sequence", "end sequence", and "delimiter", so this would mean two
(optional) more. E.g.:

typedef std::vector vector_char;

vector_char values;

// Fill with 'A', 'B', 'C'

std::cout << io::format("[", "]", ", ", "\'", "\'") << values;

Output:

['A', 'B', 'C']

However, is this overkill?

Even if the last two are optional, it means the output routines have to
output (possibly empty) strings before and after each element, in addition
to the delimiter.

Feedback is most welcome.

> > 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.

There's yet another alternative way this may be done, using "placeholder"
types, i.e.:

std::cout << io::format >(...); // Sets the format for all
vectors
std::cout << io::format<_>(...); // Sets the format for all types (defaults)

This would avoid hardcoding any defaults, as the user could change it.

The output routines could then check the formats in the following order,
e.g. for "std::vector":

If there's a format set for std::vector, use it, else
if there's a format set for std::vector<_> (all vectors), use it, else
use format for _.

Comments?


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: io operations for stl containers?

2003-03-09 Thread Terje Slettebø
>From: "Jason House" <[EMAIL PROTECTED]>


> Terje Slettebø wrote:
> >
> > >From: "Jason House" <[EMAIL PROTECTED]>
> >
> > > Is there even a way to specify/change that?
> >
> > It isn't currently, as the fundamental types aren't handled as composite
> > types, and therefore aren't formatted using any set format. Also, it
seems
> > it may not be possible in an obvious way.
> > 
> > It appears to prefer the operator<<(char) stream member function, to
this
> > free function, as it isn't called when doing "std::cout << 'A';".
>
> :(
> It would be a good question to figure out why that won't work, and how
> to fix it...  What happens, in general, if somebody want to override a
> stream operator to do something else?

Well, outputting UDTs work fine, as you can then overload the operator<<.
However, as it's already overloaded, as a member function of the stream
class, for the built-in types, it doesn't help to overload it for them.

> String output probably uses
> character output by default... it would be very bad to have a system
> that made the string "string" (no quotes) output as 's''t''r''i''n''g'

Yeah. :) basic_istream/basic_ostream have overloaded stream operators for
CharType *, so they handle strings, in other words, the iostream versions of
gets()/puts().

> > > 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?
> >
> > You're right, good point. Would it be possible to get some information
on
> > what kind of functions, if any, may be called in e.g. your debugger?
From
> > this, we may find what we can do.
>
> Well, I personally haven't gotten into the habit of calling functions
> for any debugger.

Me neither.

> I know that gdb allows that... and last that I tried
> it under the cygwin port, it wasn't very stable (but I kind of expect
> that in a cygwin port).  I do also remember hitting trouble trying to
> call templated types.  I believe that it could make calls to templated
> functions, but you needed to know the "real" name for the function...
> The base function name plus extra characters in order to distinguish
> it...  I might have gotten the "real" name off the call stack or
> something like that...
>
> Does that help to define "my debugger"?  I would hope to make it work
> for as many debuggers as possible (provided that they at least support
> making function calls)

Well, I guess that in either case, this may be handled through layering,
i.e. possibly providing convenience functions which calls the overloaded
stream operators, if the latter is difficult to call from a debugger.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: io operations for stl containers?

2003-03-09 Thread Terje Slettebø
>From: "Vladimir Prus" <[EMAIL PROTECTED]>

> Terje Slettebø wrote:
>
> > Right. 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.
>
> Uhm... I meant that the right type should be explicitly written down:
>
> template
> ostream& operator<<(ostream&, const vector& v)
> {
> const composite_format& cf = composite_format::get("vector");
> }
>
> not nice, but should work.

Ah, I see. That would work.

> > If partial specialisation was used instead, you'd still need to specify
the
> > full type (even if only the generic format is set), and then, how to
> > differentiate between specific and generic format? For example:
> >
> > std::cout << io::set_format >(...); //
> > Uses partial specialisation of class template set_format for
std::vector,
> > setting generic format
>
> Oh... so here's the gotcha! I definitely don't like this syntax for
setting
> format for *all* vectors.

Me neither. It looks like it sets it for a specific type.

> Maybe, we can go even simpler way: introduce
> separate classes for all container kinds. BGL already has vecS, setS, and
so
> on. The syntax for setting format will be
>
>   cout << io::set_format(...) ;

Yeah, that could be a way.

> > > >From what I have thought about it, allowing a generic type creates
room
> > > for unexpected behavior in output when there are composite types
> > > containing composite types, and somewhere along the lines a *generic
> > > type* default is overridden.  There might be a specific reason for a
> > > bunch of lists inside of a composite type to have a specific set of
> > > delimiters...  but it probably isn't desired for the lists inside
those
> > > lists to be forced into using the same delimiters.
> >
> > Right. Well, as mentioned, the current version uses format for specific
> > types, so in that case, you could format each part of the nested
container
> > as you wanted, as shown with the 2D-array, which of course is an array
of
> > arrays.
>
> I think that nested containers should be handled in a more explicit way.
Why
> can't we allow to explicitly set braces/delimiters for container at
certain
> nesting level:
>
>   cout << io::set_format(...)
>
> would change delimiters only for top-level container. The question is that
the
> same code can be called both from top-level and when outputting some
> container. It would be possible to just reset nesting level, and restore
it
> after outputting.

Yeah, like with I/O state savers.

I'll do some more experimentation with this, and others are free to do the
same with the code, of course.

I haven't yet updated it much, from the version at Yahoo Files, since it
hasn't really been certain what the design should be.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: io operations for stl containers?

2003-02-26 Thread Vladimir Prus
Terje Slettebø wrote:

> Right. 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.

Uhm... I meant that the right type should be explicitly written down:

template
ostream& operator<<(ostream&, const vector& v)
{
const composite_format& cf = composite_format::get("vector");
}

not nice, but should work.

> Overloading of class templates might have helped, here. E.g.:
>
> std::cout << io::set_format >(...); // Set
> specific format (io::format is a class template)
> std::cout << io::set_format(...); // Set generic format for
> std::vector (io::format overloaded with a version taking template template
> parameter, and specialised for std::vector)

Yes, it would definitely have helped.

> If partial specialisation was used instead, you'd still need to specify the
> full type (even if only the generic format is set), and then, how to
> differentiate between specific and generic format? For example:
>
> std::cout << io::set_format >(...); //
> Uses partial specialisation of class template set_format for std::vector,
> setting generic format

Oh... so here's the gotcha! I definitely don't like this syntax for setting 
format for *all* vectors. Maybe, we can go even simpler way: introduce
separate classes for all container kinds. BGL already has vecS, setS, and so 
on. The syntax for setting format will be

  cout << io::set_format(...) ;

> > >From what I have thought about it, allowing a generic type creates room
> >
> > for unexpected behavior in output when there are composite types
> > containing composite types, and somewhere along the lines a *generic
> > type* default is overridden.  There might be a specific reason for a
> > bunch of lists inside of a composite type to have a specific set of
> > delimiters...  but it probably isn't desired for the lists inside those
> > lists to be forced into using the same delimiters.
>
> Right. Well, as mentioned, the current version uses format for specific
> types, so in that case, you could format each part of the nested container
> as you wanted, as shown with the 2D-array, which of course is an array of
> arrays.

I think that nested containers should be handled in a more explicit way. Why 
can't we allow to explicitly set braces/delimiters for container at certain 
nesting level:

  cout << io::set_format(...)

would change delimiters only for top-level container. The question is that the 
same code can be called both from top-level and when outputting some 
container. It would be possible to just reset nesting level, and restore it 
after outputting.

- Volodya

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: io operations for stl containers?

2003-02-26 Thread Vladimir Prus
Hi Terje,

[...]

> > But you don't write library, put a seal on it, and stop. There's nothing
>
> wrong
>
> > with making it more flexible when users demand it. As it stands, only few
> > persons are interested in the simplest facilities. Is it worth spending
> > time
>  > on completely generic/flexible solution if no-one has expressed desire
> > for it?
>
> Right, again. What do you think of the Boost.Tuple approach?

It's sensible. OTOH, it's limited for one type, which is simpler.

> >1. Operators use fixed format: bracked list with commas between values for
> >vector, for example.
> >2. Manipulators are provided to set brackets and separators.
> >
> >I had implemented the second approach some time ago, but it turned out
> > that was overkill. So, 1) looks better now.
>
> Boost.Tuple uses the second approach, and it seems it can be useful to
> provide the possibility to change the separators. It's still a quite simple
> solution.

As I've said previously, your solution appears simple enough to me, so I've no 
problem with that kind of flexibily. The only issues are
1. How to specify formatting style for all vectors, or for all sets, etc.
2. How to handle nested containers.

I'll get to this in another email.

- Volodya

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: io operations for stl containers?

2003-02-25 Thread Terje Slettebø
>From: "Jason House" <[EMAIL PROTECTED]>
> >
> > std::vector > test;
> >
> > std::cout << test: // Using defaults
> >
> > (('A',1),('B',2),('C',3))
>
> I would suspect that chars don't get output with '' around them...

Right. I was just thinking C++ code, here. :)

> Is there even a way to specify/change that?

It isn't currently, as the fundamental types aren't handled as composite
types, and therefore aren't formatted using any set format. Also, it seems
it may not be possible in an obvious way. For example, the following
addition to the header doesn't work:

template
std::basic_ostream &operator<<
  (std::basic_ostream &stream,char value)
{
  typedef basic_composite_format format_type;

  const format_type &format=format_type::format(stream);

  stream << format.start;
  stream.operator<<(value);
  stream << format.end;

  return stream;
}

It appears to prefer the operator<<(char) stream member function, to this
free function, as it isn't called when doing "std::cout << 'A';".

> > 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 map;
> > typedef std::vector map_list;
> >
> > map_list test;
> >
> > std::cout << io::set_delimiter("\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?

I was thinking of that, yes. As well as a default, possibly user-settable,
for any type not having set an explicit format. This would let you control
the formatting in layers, so to speak:

- You could use/set the default format for all types.
- You could use/set the format for all instantiations of a given template,
e.g. std::vector.
- You could use/set the format for specific types.

If possible, it would apply the most specific format set (i.e. it would
prefer 3 to 2, to 1).

Another thing is if this layering is practically possible. :) We get into
this below here.

> > template
> > inline std::basic_ostream&
> > operator<<(std::basic_ostream& o,
> >const cons& 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?

You're right, good point. Would it be possible to get some information on
what kind of functions, if any, may be called in e.g. your debugger? From
this, we may find what we can do.

> > 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 >(...); //
Set
> > specific format (io::format is a class template)
> > std::cout << io::set_format(...); // Set generic format for
> > std::vector (io::format overloaded with a version taking template
template
> > parameter, and specialised for std::vector)
>
> Well,  would cause trouble because the std::vector requires
> extra arguments...  I don't think you could get that to compile.

True, it doesn't, because it's not currently legal C++. :) That's what I
meant with "Overloading of class templates might have helped, here." It's
not possible to overload class templates. However, this is mentioned as a
possible extension, in the "Future Directions" chapter of
Josuttis/Vandevoorde. Together with partial specialisation of function
templates, etc.

> Using
> a string might work... but using it as a template argument would
> probably cause trouble.

Yes, you can't use string literals as template parameters.

> I don't know if there is a way to use partial
> template specialization.

There is, as I showed in the following example. However, it means you have
to provide the parameters to the template, as well (e.g. std::vector), even
if you just mean to set the format for any instantiation of the template.

> There was a recent post about convertin

Re: [boost] Re: io operations for stl containers?

2003-02-24 Thread Terje Slettebø
>From: "Jason House" <[EMAIL PROTECTED]>

> Terje Slettebø wrote:
> >
> > >From: "Vladimir Prus" <[EMAIL PROTECTED]>
> >
> > Sorry for having taken so long to respond to these messages. I felt a
need
> > for a break, to consider how it might be done.
>
> I was wondering about this line of discussion earlier today... wondering
> if it died on the vine or not.  I'm glad to see that it hasn't

Right. After I had sent it, I found that "break" wasn't quite right. I meant
that I had been considering it, including what had been said in the thread.

Specifically, like I said in an earlier posting, I was wondering if there
was enough commonality to warrant a library implementation. Then I happened
to look more into Boost.Tuple, and realised that even a simple solution
could be useful, as you and others have pointed out, as well.

> > 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 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.

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 > test;

std::cout << test: // Using defaults

(('A',1),('B',2),('C',3))

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 map;
typedef std::vector map_list;

map_list test;

std::cout << io::set_delimiter("\n") << test;

Output:

(('A',1)
('B',2)
(C,3))

Or, generating program-code like listing:

std::cout << io::set_format("{\n","}\n",",\n")
  << io::set_format("{","}",", "}
  << test;

{
{'A', 1},
{'B', 2},
{'C', 3}
}

Maybe also:

std::cout << io::set_format("(\n",")\n","\n") << io::set_indent(2)
<< test;

(
  ('A',1)
  ('B',2)
  ('C',3)
)

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
inline std::basic_ostream&
operator<<(std::basic_ostream& o,
   const cons& 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.

> I think that if when
> composite_format matures, there should be a way to add non-templated
> calls to change defaults.
> maybe:
> namespace composite_format{
>   namespace tuple{
> ... set_open(char x){ return composite_format_open(x); }
>   }
> }

The manipulators might also be handled the same way as above, wrapping them
in the function.

> Actually that example doesn't quite work because  is not well
> defined.  The previous discussion of composite_fromat (or at least the
> code presented) did not allow for a generic class of types, and only
> provided functionality for a very specific type.

Right. 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 tem

Re: [boost] Re: io operations for stl containers?

2003-02-24 Thread Terje Slettebø
>From: "Vladimir Prus" <[EMAIL PROTECTED]>

Sorry for having taken so long to respond to these messages. I felt a need
for a break, to consider how it might be done.

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). To quote from the docs:

--- Start quote ---

Streaming

The global operator<< has been overloaded for std::ostream such that tuples
are output by recursively calling operator<< for each element.

Analogously, the global operator>> has been overloaded to extract tuples
from std::istream by recursively calling operator>> for each element.

The default delimiter between the elements is space, and the tuple is
enclosed in parenthesis. For Example:

tuple a(1.0f,  2, std::string("Howdy folks!");

cout << a;

outputs the tuple as: (1.0 2 Howdy folks!)

The library defines three manipulators for changing the default behavior:

- set_open(char) defines the character that is output before the first
element.
- set_close(char) defines the character that is output after the last
element.
- set_delimiter(char) defines the delimiter character between elements.

Note, that these manipulators are defined in the tuples subnamespace. For
example:

cout << tuples::set_open('[') << tuples::set_close(']') <<
tuples::set_delimiter(',') << a;

outputs the same tuple a as: [1.0,2,Howdy folks!]

The same manipulators work with operator>> and istream as well. Suppose the
cin stream contains the following data:

(1 2 3) [4:5]

The code:

tuple i;
tuple j;

cin >> i;
cin >> tuples::set_open('[') >> tuples::set_close(']') >>
tules::set_delimiter(':');
cin >> j;

reads the data into the tuples i and j.

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.

--- End quote ---

Maybe these routines could be generalised, and used for any
composite/compound type, including tuples?

If it's good enough for the standard library (given that Boost.Tuple have
been accepted in the Library TR), it may be good enough for the other types,
as well. :)

> Terje Slettebø wrote:
> >>From: "Jason House" <[EMAIL PROTECTED]>
> >
> >
> >>Terje Slettebø wrote:
> >>
> >>
> >>>Regarding this project. I've got doubts about the viability of it.
> >>
> >>Well, I'm glad you've given it a greater level of thought.  I really
like
> >
> > the idea
> >
> >>of the composite_format, and probably should try to do the same :)
> >
> >
> > Thanks for your feedback. I like the idea, as well. We have I/O for
single
> > objects, but no specific way for composites. The question is if we
should
> > have that. :) Maybe the reason we don't have it, yet, is that it may be
hard
> > to come up with a system that is general enough, yet easy to use.
>
> Most likely I don't need to say it again, but having fixed i/o operators
with
> fixed output format is better that have nothing. As you've noticed, my
> original motivation was debugging output, and I still find this important
enough.

You're right.

That was probably the motivation for Boost.Tuple's stream operators, as
well: A minimal, easy to use interface, with sensible defaults.

> >>>One thing is to create something useful. Another thing is to create
> >>>something useful as a _library_ component. As has been noted regarding
> >>>application and library development, application development and
library
> >>>development is typically quite different. With an application, you
> >
> > typically have quite specific requirements. With a library component,
however,
> > it's about anticipating future use. Or making something general enough
to be
> >>>useful as a library component.
>
> But you don't write library, put a seal on it, and stop. There's nothing
wrong
> with making it more flexible when users demand it. As it stands, only few
> persons are interested in the simplest facilities. Is it worth spending
time
> on completely generic/flexible solution if no-one has expressed desire for
it?

Right, again. What do you think of the Boost.Tuple approach?

In your original posting, you said:

>I was thinking about
>
>   
>   
>
>and so on. There are basically two approaches:
>
>1. Operators use fixed format: bracked list with commas between values for
>vector, for example.
>2. Manipulators are provided to set brackets and separators.
>
>I had implemented the second approach some time ago, but it turned out that
>was overkill. So, 1) looks better now.

Boost.Tuple uses the second approach, and it seems it can be useful to
provide the possibility to change the separators. It's still a quite simple
solution.

> >>Very true,  but some libraries are useful simply because they're simply
> > code that
> >>people would write themselves over and over... only done in a better
way.
>
> +1. I've tried to make the same point above.

You both succeeded. :)

> >>written default for this makes it all worth it for me!  The

RE: [boost] Re: io operations for stl containers?

2003-02-10 Thread Paul A. Bristow
I have followed this discussion with great interest.

I feel that the lack of an easy, 'library' 'standard' way of 'outputting' STL
objects is a major turnoff to their use.  There is persistent re-invention of
wheels. Some users may have their own special ideas about format, but a default
would be easy and essential, and be enough for most people.

If it can be used from debug tools, better still, but this should not deter work
from the promising start to allow std::cout << list;.

Paul

Paul A Bristow, Prizet Farmhouse, Kendal, Cumbria, LA8 8AB  UK
+44 1539 561830   Mobile +44 7714 33 02 04
Mobile mailto:[EMAIL PROTECTED]
mailto:[EMAIL PROTECTED]


> -Original Message-
> From: [EMAIL PROTECTED]
> [mailto:[EMAIL PROTECTED]]On Behalf Of Terje Slettebø
> Sent: Friday, February 07, 2003 9:38 PM
> To: Boost mailing list
> Subject: Re: [boost] Re: io operations for stl containers?
>
> The point with my posting was also to solicit feedback from others on the
> issue, what they think about it, what it could be used for. It would help
> define the application domain (also called problem domain).
>
> > > One thing is to create something useful. Another thing is to create
> > > something useful as a _library_ component. As has been noted regarding
> > > application and library development, application development and library
> > > development is typically quite different. With an application, you
> typically
> > > have quite specific requirements. With a library component, however,
> it's
> > > about anticipating future use. Or making something general enough to be
> > > useful as a library component.
> >
> > Very true,  but some libraries are useful simply because they're simply
> code that
> > people would write themselves over and over... only done in a better way.
>
> Yeah. Also, Björn Karlsson had an informal questionnaire on the list a while
> ago, about what people were using Boost for, and it turned out to be
> especially the simple components (not necessarily simple in implementation,
> by all means, but simple in concept) which were used, such as ref, bind,
> function objects, the smart pointers, etc.
>
> These are components which, as I mentioned, does one thing, and one thing
> well. That makes it easier to use/reuse these components in different
> contexts, as they are like building blocks.
>
> Of course "one thing" may be anything. In the case of MPL, it's a framework
> for metaprogramming, where each component does one thing. Thus, it provides
> a "language" for making things.
>
> > In the
> > current state of discussion, it sounds like something that I would
> definitely
> > use.  I've implemented poor versions on the fly in the past... always more
> > specific than composite_format...  One big use of special display
> > functions/operators is that you can call them from the debugger.  If there
> was a
> > debug-time friendly version of composite object output functions... and
> all I
> > needed to do was #include a specific header, that would be absolutely
> fantastic!
>
> Aha. Good point.
>
> > > You may do this:
> > >
> > > for(MapList::const_iterator i=list.begin(); i!=list.end(); ++i)
> > >   std::cout << '[' << i->first << ',' << i->second << "]\n";
> > >
> > > Or you may do:
> > >
> > > std::cout << composite_format("[", "]", "\n") << list;
> > >
> > > The question is, is it worth it?
> > >
> > > Of course, having defaults, the latter may be reduced to:
> > >
> > > std::cout << list;
> >
> > I absolutely hate not being able to do this last one by default.
> It would certainly be useful to come up with what we'd like to be able to
> do. We can consider this "time out", for reconsidering what we'd like to
> have.
>
>
> Regards,
>
> Terje
>
> ___
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: io operations for stl containers?

2003-02-10 Thread Vladimir Prus
Terje Slettebø wrote:

From: "Jason House" <[EMAIL PROTECTED]>




Terje Slettebø wrote:



Regarding this project. I've got doubts about the viability of it.


Well, I'm glad you've given it a greater level of thought.  I really like


the idea


of the composite_format, and probably should try to do the same :)



Thanks for your feedback. I like the idea, as well. We have I/O for single
objects, but no specific way for composites. The question is if we should
have that. :) Maybe the reason we don't have it, yet, is that it may be hard
to come up with a system that is general enough, yet easy to use.


Most likely I don't need to say it again, but having fixed i/o operators with
fixed output format is better that have nothing. As you've noticed, my 
original motivation was debugging output, and I still find this important enough.

[...]

It may actually be easier to come up with a system for serialisation, at
least when it comes to the serialised format, since the format to use for
serialisation may be easier to define. However, for operators for
human-readable I/O, there's a potentionally large variation in how you might
want to do it.


True. But there are some limits to what you could reasonably do by outputting
composite objects. For example, generation of code, or html, or something,
is not easily feasible. In fact, I cannot suggest any "advances" usage which 
is not close to serialization.

And, sure enough, I don't want to use serialization for debug output. Your 
current code is 4K. You cannot make serialization library of that size.

One thing is to create something useful. Another thing is to create
something useful as a _library_ component. As has been noted regarding
application and library development, application development and library
development is typically quite different. With an application, you


typically


have quite specific requirements. With a library component, however,


it's


about anticipating future use. Or making something general enough to be
useful as a library component.


But you don't write library, put a seal on it, and stop. There's nothing wrong
with making it more flexible when users demand it. As it stands, only few 
persons are interested in the simplest facilities. Is it worth spending time 
on completely generic/flexible solution if no-one has expressed desire for it?




Very true,  but some libraries are useful simply because they're simply


code that


people would write themselves over and over... only done in a better way.


+1. I've tried to make the same point above.


written default for this makes it all worth it for me!  The for loop has


no chance


of being evaluated properly in a debugger, but a debugger can likely call


the <<


operator with less difficulty.



Right.


+1, again.


I'm pulling at stings, but there has to be good stuff to add if we come up


with


the right aspect to develop.  I have never heard of a library designed for
evaluation of debug-time expressions...  It would be interesting to see


how


powerful of a "compile-time debugger enhancement" concept we could come up


with.


Why stop with just debugging symbols?  Make an army of debugging


functions...


This sounds interesting, but I'm not sure what those other functions could be.

- Volodya

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: io operations for stl containers?

2003-02-07 Thread Terje Slettebø
>From: "Jason House" <[EMAIL PROTECTED]>

> Terje Slettebø wrote:
>
> > Regarding this project. I've got doubts about the viability of it.
>
> Well, I'm glad you've given it a greater level of thought.  I really like
the idea
> of the composite_format, and probably should try to do the same :)

Thanks for your feedback. I like the idea, as well. We have I/O for single
objects, but no specific way for composites. The question is if we should
have that. :) Maybe the reason we don't have it, yet, is that it may be hard
to come up with a system that is general enough, yet easy to use.

Since I posted this, I've been reading the discussion on
serialisation/persistence, such as Jens Maurer's, and Robert Ramey's
recently reviewed serialisation library. It seems there were similar issues
there: It was hard to find one way of doing it, which could be generally
agreed on.

It may actually be easier to come up with a system for serialisation, at
least when it comes to the serialised format, since the format to use for
serialisation may be easier to define. However, for operators for
human-readable I/O, there's a potentionally large variation in how you might
want to do it.

In the case of the composite operators, nobody has complained about lack of
generality, or ease of use, but I've been thinking about this issue, myself.

The point with my posting was also to solicit feedback from others on the
issue, what they think about it, what it could be used for. It would help
define the application domain (also called problem domain).

> > One thing is to create something useful. Another thing is to create
> > something useful as a _library_ component. As has been noted regarding
> > application and library development, application development and library
> > development is typically quite different. With an application, you
typically
> > have quite specific requirements. With a library component, however,
it's
> > about anticipating future use. Or making something general enough to be
> > useful as a library component.
>
> Very true,  but some libraries are useful simply because they're simply
code that
> people would write themselves over and over... only done in a better way.

Yeah. Also, Björn Karlsson had an informal questionnaire on the list a while
ago, about what people were using Boost for, and it turned out to be
especially the simple components (not necessarily simple in implementation,
by all means, but simple in concept) which were used, such as ref, bind,
function objects, the smart pointers, etc.

These are components which, as I mentioned, does one thing, and one thing
well. That makes it easier to use/reuse these components in different
contexts, as they are like building blocks.

Of course "one thing" may be anything. In the case of MPL, it's a framework
for metaprogramming, where each component does one thing. Thus, it provides
a "language" for making things.

> In the
> current state of discussion, it sounds like something that I would
definitely
> use.  I've implemented poor versions on the fly in the past... always more
> specific than composite_format...  One big use of special display
> functions/operators is that you can call them from the debugger.  If there
was a
> debug-time friendly version of composite object output functions... and
all I
> needed to do was #include a specific header, that would be absolutely
fantastic!

Aha. Good point.

> > You may do this:
> >
> > for(MapList::const_iterator i=list.begin(); i!=list.end(); ++i)
> >   std::cout << '[' << i->first << ',' << i->second << "]\n";
> >
> > Or you may do:
> >
> > std::cout << composite_format("[", "]", "\n") << list;
> >
> > The question is, is it worth it?
> >
> > Of course, having defaults, the latter may be reduced to:
> >
> > std::cout << list;
>
> I absolutely hate not being able to do this last one by default.  Having a
well
> written default for this makes it all worth it for me!  The for loop has
no chance
> of being evaluated properly in a debugger, but a debugger can likely call
the <<
> operator with less difficulty.

Right.

> How easilly can a debugger print out an STL object?  I know that gdb can
call
> functions that are defined in the code.  For templated functions, this is
probably
> a major hassle.  Could there be some way to enable a debugger to call a
function
> like this?  If so, what's the best way to enable that without massive
efforts from
> the user?

I guess it depends on the debugger. I've typically done such printing
explicitly in the code, rather than invoking it in the debugger.

> I also could imagine some way of adding hooks intended for calling from a
debugger
> to alter output behavior based on what the person debugging is interested
in
> Say for instance forcing the output of a specific type to be suppressed?
>
> I'm pulling at stings, but there has to be good stuff to add if we come up
with
> the right aspect to develop.  I have never heard of a library designed for
> evaluation of debug-time 

Re: [boost] Re: io operations for stl containers?

2003-02-07 Thread Terje Slettebø
Regarding this project. I've got doubts about the viability of it.

One thing is to create something useful. Another thing is to create
something useful as a _library_ component. As has been noted regarding
application and library development, application development and library
development is typically quite different. With an application, you typically
have quite specific requirements. With a library component, however, it's
about anticipating future use. Or making something general enough to be
useful as a library component.

I've thought a lot about this, these days, regarding the composite
operators. Trying to find the essential abstraction. Clearly, they are about
passing composite objects (such as arrays, standard containers, etc.) to a
stream, so that is the abstraction. This is also something which isn't
covered much in current libraries. The question is if there's enough
commonality in this abstraction, to warrant a library implementation.

For the composite operators to be genuinely useful in a broader context, I
think it's important that they do one thing, and one thing well.

The challenge is to make something general enough, yet reasonably easy to
use. Easy things should be easy, and hard things should be possible.

My concern is, for example, for outputting a
std::vector >:

typedef std::pair Map;
typedef std::vector MapList;

MapList list;

You may do this:

for(MapList::const_iterator i=list.begin(); i!=list.end(); ++i)
  std::cout << '[' << i->first << ',' << i->second << "]\n";

Or you may do:

std::cout << composite_format("[", "]", "\n") << list;

The question is, is it worth it?

Of course, having defaults, the latter may be reduced to:

std::cout << list;

It also comes back to the question of commonality and variability.
Currently, it uses static strings for start, end, and element delimiter.
Anything else, and you need to use something else.

I was first thinking of generalising it to any string type (rather than
std::basic_string), but I've found that even that doesn't go far enough, if
you want to change it radically. I've then been thinking of the possibility
of passing a functor, instead, to the manipulator. The manipulator could
then invoke this functor for each element to be output. This would enable
things like listing element number in the output, by passing in an
appropriate functor for this. The current semantics might be catered for by
another functor, and overloaded constructors for this case may also be
provided for convenience.

BGL is similar, in that graphs are also composite objects. It uses
"visitors", which are functors with multiple member functions (not just
overloaded operator()), which are called at specific points in an algorithm.
The same could be done with the composite operators, calling the functor at
start, end and for each element.

However, as the algorithm in this case is just iterating over a sequence,
calling a functor or outputting each element, it's more or less the same as
a for-loop, or for_each.

It's also a question of what design space we are targeting: Originally,
Vladimir Prus's suggestion was for something that could help with debug
output. It's a question whether or not this can be made general enough to be
useful beyond that, and if that is even desirable, concerning things like
usability.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: io operations for stl containers?

2003-02-07 Thread Terje Slettebø
>From: "Jason House" <[EMAIL PROTECTED]>

> Jason House wrote:
>
> > Terje Slettebø wrote:
> >
> > > Another possibility might be to have a sentry object, doing automatic
state
> > > saving and restoring in the constructor and destructor. In fact, there
are
> > > already such classes in Boost: Daryle Walker's I/O state savers, which
fits
> > > this situation like a glove.
> >
> > I think that I like your solution better :)  putting it
constructor/deconstructor
> > does seem better.  I can't even argue that it's more typing for
multi-line
> > expressions...
>
> Well, I know at least have more fuel to think about...
> First of all, does your constructor take the stream as an argument?  It
would have to
> in order to do state saving in the constructor...  If so, that at least
makes prevents
> the following case (that probably needs special handling)
> {
>   io_format<> var1(...);
>   std::cout << var1 << stuff;
>   std::cerr  << var1 << more_stuff;
> }
>
> My understanding is that the constructor would not perform state saving,
but that it
> is the call to << that has to perform the locking.

Right. In the example I had, << performed the saving. In that case, it would
have to check a save-flag in the destructor. One could also pass the stream
to it in the constructor, as you say.

> So what happens when multiple streams are used?

That's no problem. The format is set for a specific stream (each stream has
its own iword/pword for the type to be output). So for the free-standing
saver, it would need to take the stream as a constructor argument.

> what happens when you have 2 or more io_formats in the same function used
on the same
> stream?
> example
> {
>   io_format var1(...), var2(...);
>   std:: cout << var1 << stuff1;
>   std::cout << var2 << stuff2;
>   std::cout << var1 << stuff3;
>   std::cout << var2 << stuff4;
>   std::cout << io_format(...) << stuff5;
> }  /* deconstruct all 3 io_format's ... not necessarilly in the right
order! */

This should work just fine. When the manipulator is used, it sets the format
given by it. When a new manipulator is used, it changes the format to the
new one. Also, the language ensures that the objects are destroyed in the
reverse order of creation, so they will all be deleted after the last
statement above.

> Here, var1, var2, and the unnamed class from the last line in the function
are all
> being deconstructed at the same time.  Some caution needs to occur here.

Well, as this version of them just sets the format, and doesn't do anything
in the destructor, their order of destruction doesn't matter for the output.

> Is that what the state-saver class you referred to does already?

That one does the restoring in the destructor. If we used the combined
setter/saver/restorer I mentioned in the posting I just sent, them only the
first of the above formats (var1), needed to save the format, to ensure that
the format wasn't changed by the output statements.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: io operations for stl containers?

2003-02-07 Thread Terje Slettebø
>From: "Jason House" <[EMAIL PROTECTED]>

> Terje Slettebø wrote:
>
> > >From: "Jason House" <[EMAIL PROTECTED]>
> > > I thought of one thing that might work reasonably well.
> > >
> > > How about making ++io_format< T > save the current format in a stack.
> > > and having io_format< T>-- restore the previously queuued format
> >
> > > so, then something like
> > >
> > > > > std::cout << ++io_format("\n|","|\n","|")--
> > > > >   << ++io_format > (&)[3][3]>("---","---","---")--
> > > > >   << board << '\n';
> > >
> > > would save and restore the formating for char(&)[3][3] and char(&)[3]
and
> > never stomp on anything else.
> >
> > In this case, it seems it saves and restores the format, before the
format
> > gets a chance to be used. In other words, the scope only covers the
state
> > saving, not the output.
>
> The idea was pre-increment and post-decrement...  I wasn't sure if pre &
post
> operators work the same for classes as they do for primitive types.

Well, you can define them like that, as well. However, even in that case,
because of operator precedence, it will evaluate ++ and --, before <<, so it
would save and restore the state, before outputting.

> > std::cout << composite_save >() << composite_format(...) <<
v <<
> > '\n';
> >
> > An alternative is a named temporary, such as:
> >
> > composite_save > sentry(stream);
> >
> > // Set format and do output
>
> I think that I like your solution better :)  putting it
constructor/deconstructor
> does seem better.  I can't even argue that it's more typing for multi-line
> expressions...

Come to think of it, we may get the best of both worlds. :) Since the format
manipulator object also is a temporary, it can do the saving/restoring. :)

You could then do e.g:

std::cout << composite_format(...,true) << v;

This saves the format, changes it, performs output, and restores the format
in the destructor.

Likewise:

composite_format sentry(std::cout,...,true); // Save format, and set new
format. Restore in destructor.

// Do output

std::cout << composite_format(...) << v; // Doesn't save/restore the format

Alternatively, it could default to save.

> When I originally started this, I said that it was the same complaint I
have about
> io_manip...  It would be neat to have a replacement/wrapper boot library
for
> io_manip.

I think the mentioned Boost I/O state savers would do that job well. That's
exactly what they are for. Have you looked at them?


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: io operations for stl containers?

2003-02-05 Thread Terje Slettebø
>From: "Larry Evans" <[EMAIL PROTECTED]>

> Terje Slettebø wrote:
> >>From: "Vladimir Prus" <[EMAIL PROTECTED]>
> >
> >>Terje Slettebø wrote:
>
> [snip]
> >
> > std::cout << io_format("\n|","|\n","|")
> >   << io_format("---","---","---")
> >   << board << '\n';
> > }
> >
> > we get:
> >
> > ---
> > |O|X|O|
> > ---
> > |X|X|O|
> > ---
> > |O|O|X|
> > ---
>
> I've used marg_ostream to format output for containers; however,
> it only used something that changed the margin.  I had to
> use an ostream<< for the particular composite to get it to work.
> However, being able to adjust the margin seems useful for
> formating most code.  Looking at the code might give you
> some more ideas about your io_format.  Unfortunately, marg_ostream
> requires wrapping the cout in a marg_ostream.
>
> Anyhow, the code is in boost files in
shared_cyclic_ptr/shared_cyclic_ptr.zip
> in boost/col_io directory.  Basically, marg_ostream++ increments the
> margin and marg_ostream-- decrements the margin.  You can also specify
> what's in the margin.  This was used to show the nesting in a fortran
> program in a parallelizing compiler.

Thanks for the tip. I'll look into it.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: io operations for stl containers?

2003-02-05 Thread Terje Slettebø
>From: "Jason House" <[EMAIL PROTECTED]>

> Terje Slettebø wrote:
>
> > > It should handle maps and pairs
> > > reasonably well.  I think that I have the same complaints about this
as
> > > io_manip
> > >
> > > The saving of information to the stream means that you can affect all
> > > future output...
> > >
> > > For instance, if you have a type
> > > map >
> > >
> > > and custom_object's stream output uses io_format >, then
> > > you are going to run into trouble if it wants a different formatting.
> >
> > Right. That's a consequence of this. As you say too, I don't know any
> > obvious alternatives, though.
>
> I thought of one thing that might work reasonably well.
>
> How about making ++io_format< T > save the current format in a stack.
> and having io_format< T>-- restore the previously queuued format

I've thought of the exact same thing. :) Not how the syntax for it would be,
but when I was thinking of this, it suddenly occurred to me: State savers!

This essentially creates a scope in the state space. As you say, you may
then read the currently set format, and restore it afterwards. The
restoration is important, and there are issues such as exception safety.

> so, then something like
>
> > > std::cout << ++io_format("\n|","|\n","|")--
> > >   << ++io_format("---","---","---")--
> > >   << board << '\n';
>
> would save and restore the formating for char(&)[3][3] and char(&)[3] and
never
> stomp on anything else.

In this case, it seems it saves and restores the format, before the format
gets a chance to be used. In other words, the scope only covers the state
saving, not the output.

Another possibility might be to have a sentry object, doing automatic state
saving and restoring in the constructor and destructor. In fact, there are
already such classes in Boost: Daryle Walker's I/O state savers, which fits
this situation like a glove.

In your original posting, you had this example:

>For instance, if you have a type
>map >

>and custom_object's stream output uses io_format >, then
>you are going to run into trouble if it wants a different formatting.

Such a custom object may then have something like the following in its
stream output:

boost::io::ios_pword_saver(stream,index);

// Set stream state, and do output.

That's all. :)

This also ensures that the state is restored properly, even in the presence
of exceptions, something the ++/-- way won't do. Of course, this requires
the pword-index, so one might make the interface more user friendly, and fit
the rest, for example by making the state saver a manipulator, itself.

As I understand, the lifetime of a temporary object extends until the end of
the full expression it's used in, so the following should be well-defined:

std::vector v;

std::cout << composite_save >() << composite_format(...) << v <<
'\n';

This saves the format at the start, and restores it at the end.

An alternative is a named temporary, such as:

composite_save > sentry(stream);

// Set format and do output

> The net effect is that you can optionally add the extra few characters and
prevent
> stomping on other code that is displaying your class.

Exactly. :)

I feel fortunate to have so many competent people around me. This certainly
gives library building a boost. :)


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: io operations for stl containers?

2003-02-05 Thread Terje Slettebø
>From: "Terje Slettebø" <[EMAIL PROTECTED]>

> const int array[3];
>
> std::cout << array;
>
> MSVC 7 - C
> Intel C++ 7  - C
> g++ 3.2   - C
>
> const char array[3];
>
> std::cout << array;
>
> MSVC 7- A (S or C)
> Intel C++ 7 - C
> g++ 3.2  - C
>
> std::cout << "Test";
>
> MSVC 7 - A (S or C)
> Intel 7  - C
> g++ 3.2   - A (S or C)
>
> In order to allow string literals to be used, without ambiguity or the
wrong
> operator being selected, it seems that one needs to overload operator<< on
> something else than T(&)[N]. T[N] isn't an option, either, as this is the
> same as overloading on T *, which means it isn't able to deduce N.
>
> This quandary may be solved by wrapping arrays in an object, which then is
> passed to the overloaded operator<<. For example:
>
> std::cout << wrap_array(array);

I found that boost::ref works for this, as well, so you may use:

char array[3[[3][3];

std::cout << array; // Overloading for this gives wrong handling of string
literals, on all compilers.

std::cout << cref(array); // Ok

For example:

void array3D_test()
{
  char boards[3][3][3]=
  {
{
  {'X','O','X'},
  {'O','X','O'},
  {'X','O','X'}
},
{
  {'X','X','X'},
  {'X','O','X'},
  {'X','X','X'}
},
{
  {'O','X','O'},
  {'X','X','X'},
  {'O','X','O'}
}
  };

  std::cout << composite_format
>("\n|","|\n","|")
<< composite_format
>("---","---","---")
<< composite_format
>("--- Boards ---\n\n","\n\n--- Boards ---","\n\n")
<< boost::cref(boards) << '\n';
}

Output:

--- Boards ---

---
|X|O|X|
---
|O|X|O|
---
|X|O|X|
---

---
|X|X|X|
---
|X|O|X|
---
|X|X|X|
---

---
|O|X|O|
---
|X|X|X|
---
|O|X|O|
---

--- Boards ---

I'll work on a version that works with this.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: io operations for stl containers?

2003-02-05 Thread Terje Slettebø
>From: "Paul A. Bristow" <[EMAIL PROTECTED]>

> This looks really neat - and potentially very useful.

Thanks. :)

> Sadly, array is one of the most interesting cases - so I'm sure I won't be
the
> only one 'watching this space'.

I've looked more into it, and it seems this is a problem not just for MSVC,
but a problem with the current way of doing it, overloading operator<< for
T(&)[N], sinch string literals has the type "const char[N]", as well...

With overloaded operator<< for T(&)[N], and using "std::cout << "Test" ",
g++ gives an ambiguity error, while on Intel C++, it selects the composite
overload, resulting in funny output: It tries to output the null-terminator,
as well, not knowing that for character strings, this is a string
terminator. Besides, it can't really know if the user meant to send a
character string, or a non-null-terminated character array.

It seems the differences is down to subtle implementation differences. Here
are the results, when an overloaded operator<< with T[N] is defined (S -
string-literal operator, C - composite operator (T(&)[N]), A - ambiguous):

const int array[3];

std::cout << array;

MSVC 7 - C
Intel C++ 7  - C
g++ 3.2   - C

const char array[3];

std::cout << array;

MSVC 7- A (S or C)
Intel C++ 7 - C
g++ 3.2  - C

std::cout << "Test";

MSVC 7 - A (S or C)
Intel 7  - C
g++ 3.2   - A (S or C)

In order to allow string literals to be used, without ambiguity or the wrong
operator being selected, it seems that one needs to overload operator<< on
something else than T(&)[N]. T[N] isn't an option, either, as this is the
same as overloading on T *, which means it isn't able to deduce N.

This quandary may be solved by wrapping arrays in an object, which then is
passed to the overloaded operator<<. For example:

std::cout << wrap_array(array);

Comments/suggestions?

> PS composite_format is a bit long, but I can't suggest better.

I know, but I don't know any better, either. I see that Volodya suggests
composite_io in another posting. That's another possibility. Anyway, I guess
what's most important is to get the functionality in place. A default system
may make it easier, as well.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: io operations for stl containers?

2003-02-05 Thread Vladimir Prus
Terje Slettebø wrote:


By the way, just for fun. Adding the following output operator for


arrays,


to the header I gave in the previous posting:



---
|O|X|O|
---
|X|X|O|
---
|O|O|X|
---

"Shall we play a game?" :)


Sure thing :-)



I guess you maybe got the "War Games" reference? :)


Don't know what this reference is, but played that game in school.



2. I think that we better have separate headers for stl containers, like
   suggested in my original email (, etc). That's
   because I'd like to output maps, but would not like to include 
when I need to output a vector.



Heh, just before I got this posting, I had added the following comment in
the header:


[...]

We're in total agreement until now.


I'll get back to your other comments, I just need to look more into
how it might be done.


Maybe you know a better solution already, but thinking about per-conainer
format is arrive to:

We basically need the following (note that "..." are no metacharacters)

  template class container>
  class basic_composite_io {
  int get_pword_index();
  }

  template
  int basic_composite_io >::get_pword_index() {
	static int i = ios_base::xalloc();
return i;
  }

Since we can specialize on template name, we have to fake that:

  template
  int basic_composite_io >::get_pword_index() {
 static int i = get_vector_pword_index();
 return i;
  }

Why can't we afford to create a function for each supported container,
make it call xalloc, and return that value. Not very nice, but works.

Another alternative is to create custom 'xalloc' which takes a string,
and does not allocate new index if an index for that string is already
allocated.

  template
  int basic_composite_io >::get_pword_index() {
 static int i = xalloc("std::vector");
 return i;
  }

Would this be sufficient?

- Volodya

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



RE: [boost] Re: io operations for stl containers?

2003-02-04 Thread Paul A. Bristow
This looks really neat - and potentially very useful.

Sadly, array is one of the most interesting cases - so I'm sure I won't be the
only one 'watching this space'.

Thanks

Paul

PS composite_format is a bit long, but I can't suggest better.


Paul A Bristow, Prizet Farmhouse, Kendal, Cumbria, LA8 8AB  UK
+44 1539 561830   Mobile +44 7714 33 02 04
Mobile mailto:[EMAIL PROTECTED]
mailto:[EMAIL PROTECTED]



> Looking at the error messages, and from what I've heard, it may be that it
> has problems with template friends (which is what the operator<< is). If
> that's the case, the workaround should be very easy - making it a
> free-function template.
>
> I did that, now, and it works. :)
>
> At least the vector_pair_test(). The array2D_test() uses a little fancy
> code, such as passing the type reference to array as a template parameter,
> and it seems MSVC 7.0 has some problems with this. Anyway, that was just to
> demonstrate usage with built-in types, as well, such as arrays. I'll look
> into it.
>
> There wasn't really any need for it to be a friend function, as it didn't
> access any private parts. It was just defined inside the class for
> convenience.
>
> I've also tested it on Intel C++ 7.0 in strict mode and g++ 3.2, so the code
> should be conformant, at least.
>
> Thanks for the report. I hadn't yet got around to do more portability
> testing, but intend to do that, including writing more tests for it. I've
> updated the version at Yahoo Groups with the above changes.
>
>
> Regards,
>
> Terje
>
> ___
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: io operations for stl containers?

2003-02-04 Thread Terje Slettebø
>From: "Jason House" <[EMAIL PROTECTED]>

> Terje Slettebø wrote:
> > and given this:
> >
> > int main()
> > {
> > char board[3][3]=
> > {
> > {'O','X','O'},
> > {'X','X','O'},
> > {'O','O','X'}
> > };
> >
> > std::cout << io_format("\n|","|\n","|")
> >   << io_format("---","---","---")
> >   << board << '\n';
> > }
> >
> > we get:
> >
> > ---
> > |O|X|O|
> > ---
> > |X|X|O|
> > ---
> > |O|O|X|
> > ---
>
> Hey, that's pretty cool.  I'm glad to see the ability to format items
> inside of a container as well.

I'm glad you like. :) Yes, it applies operator<< recursively, using
overloading, and any format settings for the given type, so for the outer
array, it matches the second format above, and for the inner it matches the
first one.

> It should handle maps and pairs
> reasonably well.  I think that I have the same complaints about this as
> io_manip
>
> The saving of information to the stream means that you can affect all
> future output...
>
> For instance, if you have a type
> map >
>
> and custom_object's stream output uses io_format >, then
> you are going to run into trouble if it wants a different formatting.

Right. That's a consequence of this. As you say too, I don't know any
obvious alternatives, though.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: io operations for stl containers?

2003-02-04 Thread Terje Slettebø
>From: "Paul A. Bristow" <[EMAIL PROTECTED]>

> This looks most useful - potentionally :-(
>
> Alas the two files, test and composite_stream_operators.hpp
>
> http://groups.yahoo.com/group/boost/files/composite_stream_operators/).
>
> won't compile on MSVC 7.0.
>
> test_composite_format.cpp
> test_composite_format.cpp(43) : error C2679: binary '<<' : no operator
found
> which takes a right-hand operand of type 'composite_format' (or there
is no
> acceptable conversion)
> with
> [
> T=char (&)[3]
> ]
>
> and similarly for T=Map
>
> Is the cause/workaround obvious?

Looking at the error messages, and from what I've heard, it may be that it
has problems with template friends (which is what the operator<< is). If
that's the case, the workaround should be very easy - making it a
free-function template.

I did that, now, and it works. :)

At least the vector_pair_test(). The array2D_test() uses a little fancy
code, such as passing the type reference to array as a template parameter,
and it seems MSVC 7.0 has some problems with this. Anyway, that was just to
demonstrate usage with built-in types, as well, such as arrays. I'll look
into it.

There wasn't really any need for it to be a friend function, as it didn't
access any private parts. It was just defined inside the class for
convenience.

I've also tested it on Intel C++ 7.0 in strict mode and g++ 3.2, so the code
should be conformant, at least.

Thanks for the report. I hadn't yet got around to do more portability
testing, but intend to do that, including writing more tests for it. I've
updated the version at Yahoo Groups with the above changes.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: io operations for stl containers?

2003-02-04 Thread Larry Evans
Terje Slettebø wrote:

From: "Vladimir Prus" <[EMAIL PROTECTED]>




Terje Slettebø wrote:


[snip]


std::cout << io_format("\n|","|\n","|")
  << io_format("---","---","---")
  << board << '\n';
}

we get:

---
|O|X|O|
---
|X|X|O|
---
|O|O|X|
---


I've used marg_ostream to format output for containers; however,
it only used something that changed the margin.  I had to
use an ostream<< for the particular composite to get it to work.
However, being able to adjust the margin seems useful for
formating most code.  Looking at the code might give you
some more ideas about your io_format.  Unfortunately, marg_ostream
requires wrapping the cout in a marg_ostream.

Anyhow, the code is in boost files in shared_cyclic_ptr/shared_cyclic_ptr.zip
in boost/col_io directory.  Basically, marg_ostream++ increments the
margin and marg_ostream-- decrements the margin.  You can also specify
what's in the margin.  This was used to show the nesting in a fortran
program in a parallelizing compiler.



___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



RE: [boost] Re: io operations for stl containers?

2003-02-04 Thread Paul A. Bristow
This looks most useful - potentionally :-(

Alas the two files, test and composite_stream_operators.hpp

http://groups.yahoo.com/group/boost/files/composite_stream_operators/).

won't compile on MSVC 7.0.

test_composite_format.cpp
test_composite_format.cpp(43) : error C2679: binary '<<' : no operator found
which takes a right-hand operand of type 'composite_format' (or there is no
acceptable conversion)
with
[
T=char (&)[3]
]

and similarly for T=Map

Is the cause/workaround obvious?

Thanks

Paul



Full messages:

test_composite_format.cpp
test_composite_format.cpp(29) : error C2679: binary '<<' : no operator found
which takes a right-hand operand of type 'composite_format' (or there is no
acceptable conversion)
with
[
T=Map
]
j:\Cpp\composite_format\composite_stream_operators.hpp(42) : warning C4933:
'std::basic_ostream &operator <<(std::basic_ostream &,const
basic_composite_format &)' and 'std::basic_ostream &operator
<<(std::basic_ostream &,const
basic_composite_format &)' only differ by top-level CV-qualifiers in
their arguments.  This usage is deprecated and may be an error in the future
with
[
CharType=char,
T=char (&)[3]
]
j:\Cpp\composite_format\composite_stream_operators.hpp(42) : see
declaration of 'operator`<<''
j:\Cpp\composite_format\composite_stream_operators.hpp(42) : see
declaration of 'operator`<<''
j:\Cpp\composite_format\composite_stream_operators.hpp(83) : see
reference to class template instantiation 'basic_composite_format'
being compiled
with
[
CharType=char,
T=char (&)[3]
]
test_composite_format.cpp(42) : see reference to class template
instantiation 'composite_format' being compiled
with
[
T=char (&)[3]
]
test_composite_format.cpp(43) : error C2679: binary '<<' : no operator found
which takes a right-hand operand of type 'composite_format' (or there is no
acceptable conversion)
with
[
T=char (&)[3]
]
j:\Cpp\composite_format\composite_stream_operators.hpp(42) : warning C4933:
'std::basic_ostream &operator <<(std::basic_ostream &,const
basic_composite_format &)' and 'std::basic_ostream &operator
<<(std::basic_ostream &,const
basic_composite_format &)' only differ by top-level CV-qualifiers in
their arguments.  This usage is deprecated and may be an error in the future
with
[
CharType=char,
T=char (&)[3][3]
]
j:\Cpp\composite_format\composite_stream_operators.hpp(42) : see
declaration of 'operator`<<''
j:\Cpp\composite_format\composite_stream_operators.hpp(42) : see
declaration of 'operator`<<''
j:\Cpp\composite_format\composite_stream_operators.hpp(83) : see
reference to class template instantiation 'basic_composite_format'
being compiled
with
[
CharType=char,
T=char (&)[3][3]
]
test_composite_format.cpp(43) : see reference to class template
instantiation 'composite_format' being compiled
with
[
T=char (&)[3][3]
]

Build log was saved at "file://j:\Cpp\composite_format\Debug\BuildLog.htm"
composite_format - 2 error(s), 2 warning(s)

and for simpler tests like a pair, vector ...

test_composite_format.cpp(25) : error C2679: binary '<<' : no operator found
which takes a right-hand operand of type 'composite_format' (or there is no
acceptable conversion)
with
[
T=std::pair
]
test_composite_format.cpp(36) : error C2679: binary '<<' : no operator found
which takes a right-hand operand of type 'composite_format' (or there is no
acceptable conversion)
with
[
T=std::vector>
]
test_composite_format.cpp(37) : error C2679: binary '<<' : no operator found
which takes a right-hand operand of type 'composite_format' (or there is no
acceptable conversion)
with
[
T=std::vector>
]


> -Original Message-
> From: [EMAIL PROTECTED]
> [mailto:[EMAIL PROTECTED]]On Behalf Of Terje Slettebø
> Sent: Tuesday, February 04, 2003 1:46 PM
> To: Boost mailing list
> Subject: Re: [boost] Re: io operations for stl containers?
>
>
> >From: "Vladimir Prus" <[EMAIL PROTECTED]>
>
> > Terje Slettebø wrote:
> >
> > > Incidentally, I've just made a version that do

Re: [boost] Re: io operations for stl containers?

2003-02-04 Thread Terje Slettebø
>From: "Vladimir Prus" <[EMAIL PROTECTED]>

> Terje Slettebø wrote:
>
> > There are also some other issues: The current version assumes
basic_string
> > for the delimiters. I've found it hard to let it take an arbitrary
string
> > type, as the format-object (which the manipulator,
basic_composite_format,
> > doubles as) stores a format parameterised on type to output and
character
> > type. The latter is so that if multiple streams with different character
> > types are used, they should not use the same format-object..
>
> Is assuming basic_string really a problem?

No, not really. I was just thinking of generality. However, as it is, it
needs the character type, anyway.

> > By the way, just for fun. Adding the following output operator for
arrays,
> > to the header I gave in the previous posting:
>
> > ---
> > |O|X|O|
> > ---
> > |X|X|O|
> > ---
> > |O|O|X|
> > ---
> >
> > "Shall we play a game?" :)
>
> Sure thing :-)

I guess you maybe got the "War Games" reference? :)

> > I've uploaded the new version here
> > (http://groups.yahoo.com/group/boost/files/composite_stream_operators/).
>
> There are two more points:
> 1. Could you put this to the sandbox, too. Yahoogroups is less convenient.

Sure. :)

> 2. I think that we better have separate headers for stl containers, like
> suggested in my original email (, etc). That's
> because I'd like to output maps, but would not like to include 
when
> I need to output a vector.

Heh, just before I got this posting, I had added the following comment in
the header:


///
// The following are just a few examples of output operators, for some of
the
// containers and types in the standard library. These could well be
separated
// in other files. That would also reduce the number of includes.

///

:)

Will do. I'll get back to your other comments, I just need to look more into
how it might be done.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: io operations for stl containers?

2003-02-04 Thread Terje Slettebø
>From: "Vladimir Prus" <[EMAIL PROTECTED]>

> Terje Slettebø wrote:
>
> > Incidentally, I've just made a version that does exactly this. :) I've
> > attached it, including a test, with this posting.
>
> I've take a look and I like it -- quite lean and does the work.

Thanks. :)

> I've some concerns, though:
>
> 1. Are "default" breaces/separators possible?  I'd rather not use
> io_format every time I had to output a vector.

Good point. As it is now, it just defaults to empty strings for the
separators. Any idea how to specify such a default? If it's specified in the
header, it may be hard to select one that is sensible for all people.

> 2. Is that good idea to set brace style on vector and vector
> separately? It would increase pword() array, and not sure if this will
> benefit us much. Are nested containers the primary motivation?

Another good point. I guess there isn't any point in separate formats for
different element types, no.

The way it works now is that it instantiates an
basic_composite_format (name changed from
basic_io_format), containing a static function with a static xalloc() index,
for each type to be output. Thus, it's parameterised on a type, not a
partially specified type.

I'll look into this, as well. Partial specialisation, inheriting from a
less-parameterised base comes to mind.

There are also some other issues: The current version assumes basic_string
for the delimiters. I've found it hard to let it take an arbitrary string
type, as the format-object (which the manipulator, basic_composite_format,
doubles as) stores a format parameterised on type to output and character
type. The latter is so that if multiple streams with different character
types are used, they should not use the same format-object..

This means that one must know the character type of the delimiter strings,
in order to parameterise the format object correctly. That's why
basic_string is used, as you then get access to the character type.

By the way, just for fun. Adding the following output operator for arrays,
to the header I gave in the previous posting:


///
// operator<<(stream,T[N])

///

template
std::basic_ostream &operator<<
  (std::basic_ostream &stream,T (&array)[N])
{
  typedef basic_io_format format_type;

  const format_type &format=format_type::format(stream);

  stream << format.start << array[0];

  for(std::size_t i=1;i!=N;++i)
stream << format.delimiter << array[i];

  stream << format.end;

  return stream;
}

and given this:

int main()
{
char board[3][3]=
{
{'O','X','O'},
{'X','X','O'},
{'O','O','X'}
};

std::cout << io_format("\n|","|\n","|")
  << io_format("---","---","---")
  << board << '\n';
}

we get:

---
|O|X|O|
---
|X|X|O|
---
|O|O|X|
---

"Shall we play a game?" :)

By the way, in the first posting, I figured you knew about stream iterators,
so I was a little puzzled, but then it turned out I had just misunderstood
what you meant. Reading it more carefully later, I saw that you did mention
stream operators.

The names and interface is just chosen tentatively, and I'm open to
suggestions for better names. I changed the "*io_format" names to
"*composite_format", as it reflects better what it does, and reduces the
chance for name collision. I didn't want to call it container_format, or
something like that, as it's not restricted to containers, but may output
any composite object, given suitably defined output operators (such as
std::vector, std::pair, arrays, etc.)

Thanks for the feedback.

I've uploaded the new version here
(http://groups.yahoo.com/group/boost/files/composite_stream_operators/).


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: io operations for stl containers?

2003-02-03 Thread Terje Slettebø
>From: "Vladimir Prus" <[EMAIL PROTECTED]>

> Terje Slettebø wrote:
> >>From: "Vladimir Prus" <[EMAIL PROTECTED]>
> >
> >>after having to output std::vector to stream again and again using
custom
> >>solution, I started to wonder why we don't have a solution in boost.
> >>Does it makes sense to include operators<< for vectors, sets, etc?
> >>
> >>I was thinking about
> >>
> >>   
> >>   
>
> > You can do this quite well using the standard library and stream
iterator
> > adapters. This may do both of your approaches above. For example:
>
> I certainly know that.

I guessed you might. However, the solution seemed like a good match to your
question, given that you didn't give any code example of its use. You
mentioned outputting a vector to a stream, using custom separators, and
that's what this does.

> > std::cout << "Print vector\n";
> > std::copy(list.begin(),list.end(),Out(std::cout,"\n"));
>
> And I don't like it in the least. Compared with
>
> std::cout << "new path is " << v << "\n";

I understand what you mean now.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost