Boost logo

Boost :

From: Rob Stewart (stewart_at_[hidden])
Date: 2004-09-03 20:39:19


From: "Jonathan Turkanis" <technews_at_[hidden]>
> "Rob Stewart" <stewart_at_[hidden]> wrote in message
> news:200409031905.i83J5JU21799_at_lawrencewelk.systems.susq.com...
> > From: "Jonathan Turkanis" <technews_at_[hidden]>
> > > "Thorsten Ottosen" <nesotto_at_[hidden]> wrote in message
>
> > > One of the original motivations for introducing the i/o categories (they
> turned
> > > out to be useful for a lot of other things) was to avoid having separate
> > > functions push_filter and push_resource. I consider it a major
> simplification of
> > > the interface.
> >
> > I agree with Thorsten that some means of ensuring that parts
> > aren't assembled in the wrong order would be helpful. Whether
> > that means separate functions, or detection of the type of object
> > being pushed, it seems like preventing misuse should be a bigger
> > priority than "a major simplification of the interface."
>
> I'm not sure I follow. You already get a runtime error if you try to add a
> filter or resource to a chain that is already complete. This is mention in the
> specification for push (see http://tinyurl.com/49j6u) E.g.,
>
> filtering_ostream out;
> out.push(zlib_compressor());
> out.push(file_sink("hello.z"));
> out.push(base64_encoder()); // error !!
> out.push(tcp_sink(www.microsoft.com, 80)); // error !!
>
> Isn't this enough? (Maybe it should be an assertion failure instead of an
> exception.)

Oh, right. That's good, and is flexible for runtime assembly of
the filters and resource.

> Perhaps you would like a compile-time error instead. Note that having separate

Where possible, that's certainly preferable.

> functions for pushing filters and resources would not help in that case. To
> generate a compile-time error would require that the types of all the filters
> and resources be encoded into the type of the filtering stream. This was
> suggested last year by Larry Evans and recently by Robert Ramey (if I understood
> hime correctly.)
>
> The problems are:
>
> - much more complex interface

This is a subjective judgment I can't evaluate due to lack of
information.

> - less flexible a runtime

I can see that is a problem and I can imagine determining the
filters to assemble at runtime, so this would be an issue.

> - neglible gain in efficiency, since most filtering operations aren't inlineable

The request wasn't about efficiency but safety.

> Finally, it's already the programmer's responsibility to ensure that the filters
> are added in the right order -- no amount of template magic will guarantee
> this -- so making sure to add the resource at the end is not much of an extra
> burden.

You're right, and I already acknowledged (quoted below) that
there are many places in which a programmer can hang himself.
The flexibility of what you have in place increases runtime
possibilities, and can be wrapped to make it safer as discussed
below.

> > There are plenty of places where one can misuse existing
> > libraries, including the Standard Library, so perhaps requiring
> > that protection from this library is misguided. So, here's
> > another approach: perhaps you could create a set of overloaded
> > make_* functions that take a varying number of filter arguments
> > followed by an optional (via overloading) resource argument.
> > Then, those functions can ensure that if there is a resource, it
> > is push()'d last.
>
> Yes, that would work. There are two versions I can think of:
>
> 1. Orginally I had a function link(...) which created an inline chain of filters
> and resources, but I eliminated it to make the library smaller. It didn't occur
> to me to add a compile-time check that the last element was a resource; in fact,
> I thought it would also be useful for chaining filters alone. However, this
> might be a good reason to restore the function link, with the added check.

This is rather like using smart pointers. You can always call
new and delete, and work with raw pointers, but it's up to you to
guard against errors, including in the face of exceptions. When
using smart pointers, which are wrappers around raw pointers, you
gain safety.

This should in no way be considered a prerequisite to acceptance
of the library.

> 2. Dietmar Kuehl mentioned a piping syntax originall proposed by JC van Winkel.
> E.g.,
>
> filtering_stream
> out( base64_encoder() | zlib_compressor() | file_sink("file") );
>
> This syntax, too, could be modified to do a compile-time check that the last
> item in the chain is a resource.

Does it have to be a resource? Is the check actually to ensure
that no filter follows a resource?

> I like both of these ideas as a syntactic convenience but not as a way to
> enforce at compile time that resources are added last. For this enforcement to
> have teeth, it would be necessary to remove the stack interface, which would be
> considered 'unsafe'. But the stack interface is natural and convenient, and
> essential for some purposes.

Don't do that; keep things as they are.

> I sort of feel like I'm beating a dead horse :-) Is a runtime error (or
> assertion failure) sufficient, or do you feel strongly that there needs to be a
> compile-time check?

I think that what you have is fine, but that a safer means built
atop what exists is a better approach and can be added later as
time permits.

-- 
Rob Stewart                           stewart_at_[hidden]
Software Engineer                     http://www.sig.com
Susquehanna International Group, LLP  using std::disclaimer;

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk