Boost logo

Boost :

From: Philippe Mori (philippe_mori_at_[hidden])
Date: 2005-01-10 18:56:40


>
> If it really were possible to reuse existing code, as you orginally
> suggested,
> then it would be a clear win. However, I haven't yet seen an example of a
> pre-existing procedure which meets the requirements of the proc_as_filter
> class.
> Therefore, I first must decide whether writing a filter as a function
> which
> reads from standard input and writes to standard output is ever the best
> way to
> write a filter, given the other choices that the library provides. You
> clearly
> think the answer is yes, but I'd like to see some examples.
>
> Second, is there any reason to prefer functions with the signature
>
> void (*) () [A]

This is too much strict to force the uses of cin and cout... Any other
possible uses would require either to redirect inputs (which might not
always be possible particulary if there are multiple thread or if some
code assumes that cin or cout is the standard output and can be used
freely).

>
> over member functions taking references to an input stream and an output
> stream:
>
> struct myfilter {
> void filter(std::istream&, std::ostream&); [B]
> };
>
> This is more in keeping with the reset of the library.
>

This is better, but why not uses operator() instead of a named function
since it would allows us to uses ordinary function of function object
and it will works well with boost::function.

> Finally, why shouldn't the signature be:
>
> struct myfilter {
> template<typename Source, typename Sink>
> void filter(Source& src, Sink& snk);
> [C]
> };
>
> ?
>

This, combined with my suggestion of using operator() would be the best
solution in my opinion. But if the Source and Sink can have arbitrary type
we should have a bunch of traits that would allows the code to works
with most or all type of Source and Sink.

OTOH, if someone only need to support one kind of stream in it algorithm
then it might prefer to implement the non-template version.

> I expect the answer is that you want to be able to use formatting i/o
> functions
> in the implementation of filter(). Here, again, I'd like to see some
> examples to
> prove that it is useful.
>
> Personally, I'd prefer [C], and I'd like to change the specification so
> that
> instead of filter() consuming all the characters in src, it reads some
> source
> source characters from src, writes some characters to snk and returns a
> status
> code, e.g. partial, eof or ok.
>
>>> However, I should be able to extend it so that if a chain contains
>>> both a source
>>> and a sink, boost::io::copy is invoked. E.g.,
>>>
>>> source() | filter1() | filter2() | filter3() | sink()
>>>
>>> would be equivalent to
>>>
>>> filtering_ostream out(filter1() | filter2() | filter3() | sink());
>>> boost::io::copy(source, out);
>>>
>>> If I can make this work, and there are no objections, I'll add it.
>>
>> This is what I am ultimately striving for. Is there any reason why the
>> source() and sink() can not be assumed to be cin and cout
>> respectively when absent?
>
> Yes. When you use the pipe operator you don't always want to form a
> complete
> chain:
>
> filtering_ostream out(filter1() | filter2() | filter3());
> out.push(sink());
>

Well passing filters to the constructor might be more limitating that
working with objects. So I thing we should be able to do something
like:

    filtering_ostream out;
    out < cin;
    out | filter1() | filter2();
    out | filter3();
    out > cout;

Philippe


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