From: Jonathan Turkanis (technews_at_[hidden])
Date: 2004-09-14 13:41:07
"Rob Stewart" <stewart_at_[hidden]> wrote in message:
Continuing where I left off yesterday.... Again, I'll only comment on the parts
where I disagree, don't understand or believe more explanation is necessary.
> You have two sections with the same heading;
I'm emulating the Dinkumware documentation style. For overloaded functions,
there is a heading like
followed by a recapitulation of the relevant part of the synopsis, followed by a
decription of each member. I've found the documentation hard to read when I
group too many overloads together, since I end up writing stuff like "this
seventh member constructs a ..."
So I split them up, but give them headers with the same name. Perhaps heading
streambuf_facade::streambuf_facade (From Policy)
would be better in cases like this.
> both should fall
> under the heading "Constructors." Otherwise,
> "streambuf_facade::streambuf_facade" should be written as
I don't see how adding the template arguments helps.
> The first streambuf_facade::streambuf_facade
> "Before the instance can be used for i/o, one of its..."
> The second streambuf_facade::streambuf_facade
> "Constructs a streambuf_facade which is ready to perform i/o,
> where the parameters have the following interpretations:"
> You don't call out function parameters like this many other
> places. There's nothing wrong with it, but you should choose to
> explain them in a paragraph or a list and do that throughout the
I choose a table explaining the parameters only when I thought it would be the
more helpful format. There are cases where it seems unnecessary, e.g.,
mapped_file_sink(const std::string& path);
Constructs a mapped_file_sink to access the file with the given pathname.
path - the pathname of the file to be accessed.
Again, adding the template arguments just makes the headers harder to read, IMO.
> "Assocaites the given instance of T with this instance of
> streambuf_facade, if there is no such instance currently
I don't understand the ^^^^ under 'there is'. I guess I'm viewing your
corrections with an incompatible font.
> Class template stream_facade
> Where are the streambuf examples? You said they were the
> "fundamental components" of the library.
Good point. Based on the comments of reviewers, I plan to
1. explain early in the docs the roles of stream buffers and streams in the
standard library i/o framework
2. explain that the streams in the current library are provided only as a
3. Show how to use an arbitrary streambuf with a plain istream or ostream
4. Explain that most of the examples will use streams, since these are more
familiar and will probably represent the most comon use of the library.
> There are two, identical declarations of
Thanks, the second should be filtering_stream.
> Do any of these techniques apply to filtering_streambufs?
They all apply to the streambuf variants of the stream templates used.
> "* converting_streambuf: A wide-character stream buffer template
> having an interface essentially identical to
> Don't break the paragraph here.
Seems to be a mozilla bug.
> filtering_streambuf, with the following additional property:
> after zero or more wide-character filters have been added to the
> chain, a sequence of zero or more narrow-character filters and a
> narrow character resource may be added. A converter is inserted
> automatically between the final wide-character filter and the
> first narrow-character filter or resource."
> Rephrasing that will simplify it and make it clear:
> ...essentially identical to filtering_streambuf, which
> automatically inserts a converter between the last wide
> character filter, if any, and the first narrow character
> filter or resource. (Any wide character filters must precede
> the narrow character filters and resource in the chain.)
I agree that my wording is awkward, but I'm not sure I like your suggestion. How
essentially identical to filtering_streambuf except that
both wide- and narrow-character filters and resources
can be added to it. The only restriction is that the wide-
character components must come first. When the first
narrow-character components is added, the libray
automatically inserts a code_converter.
> You mention a convenience function named "copy" but the only
> function shown is operator <<.
I agree this looks funny, and will have to be changed. Refering to the
supposedly familiar overload of basic_ostream::operator<< was supposed to be a
quick way of explaining what copy does. But it clearly didn't work.
> "The class templates converter is...and produces a resource with
> wide character type"
> a wide
A resource adapter which which takes a narrow-character resource type
and produces a wide-character resource type by introducing a
layer of code conversion using a std::codecvt.
> Calling a constructor a member, however accurate, is odd. Why
> not just call it a constructor?
Good point. I thought I was following the Dinkumware convention, but having just
checked, I see that I wasn't.
> "Assocaites the given instance of Resource with this instance of
> converter, if there is no such instance currently associated;
> otherwise, throws std::ios_base::failure."
> "Associates" is misspelled, but rephrasing it would work well:
> Makes a copy of the Resource to be used by the converter. If
> the converter already has a Resource, it throws
I agree that associate/dissociate is awkward. How about attach/detach?
> I don't think "associates" leaves out an important detail,
> suggesting that the Resource is tracked by pointer and that the
> Resource's lifetime must extend to the next call to close().
I'm planning an entire section on lifetime management issues.
> "The third parameter determines the size of the buffer or buffers
> used for code conversion."
> for the
My formulation sound more natural to me.
> "Disassociates from this instance of converter any instance of
> the resource type Resource currently associated with it, calling
> cleanup functions as appropriate and destroying the associated
> instance of Resource."
> This is awkwardly phrased. I suggest:
> Destroys the converter's current Resource, if any, calling the
> cleanup functions of any filters and the Resource, as
Detaches the converter's current Resource, if any, and destroys it,
after calling any appropriate cleanup functions
> I don't think "dissociate" (not "disassociates," BTW) is
Thanks. Google tells me that 'dissociate' is about twice as common as
'disassociate'. Maybe 'disassociate' should mean 'insult an attorney who hasn't
> The Boost Iostreams Library
> The text is formatted differently than on other pages for this
> heading level.
I used H5 here because I thought the higher levels looked odd. But I think it's
a moot point because I should move the rationale to the central Rationale
> Exception Safety
> "1. Resources are freed by calling destructors or
> close, if appropriate."
> Don't break the line between "or" and "close."
Mozilla -- up to her old tricks.
> "Conditions 2. and 3. rely on the specification of the filter and
> resource concepts. Note that there is no guarantee that a
> stream's or stream buffer's character sequences are in a
> consistent state, i.e., that data has not been corrupted, and no
> way in general to determine the state of these sequences after an
> After reading this paragraph, I'm left to wonder whether removing
> and replacing the resource, as described in 3.b, means that the
> state of the character buffers is well-defined or still unknown
> as described here. IOW, this paragraph seems to contradict 3.b
> and should be rephrased to clarify how the state of the buffers
> can be known and corrected.
Good point. After an exception, and before the chain is modified, there is no
> "Thanks to Angelika Langer and John Torjo for discussion of
> What does "for discussion of exceptions" mean? Did you have
> conversations with them on the subject? Then you need to write,
> "for our discussions on exceptions and exception handling."
Yes, this sounds awkard. How about:
Angelika Langer and John Torjo provided helpful comments on the role of
exceptions in the standard iostreams library.
> "The type of object which a basic_regex_filter uses to...."
> formatter is the
Do you feel the same way about elision of the subject in function documentation
which begins with "Returns"?
> "Since Boost.Function objects are implictly constructible from
> function objects with the correct signature, users of regular
> expression filters may define their own function objects with the
> correct signature and pass them to the basic_regex_filter
> This is incomplete. One can write free functions, lambda
> functions, etc. that satisfy Boost.Function to create formatters.
users of regular expression filters may pass any function or function
object to the basic_regex_filter constructor as long as its signature is
> "replace - A function which will be passed each match_results
> object in succession and whose return values will be be used as
> replacement text"
> Rewording this will make it clearer:
> A Boost.Function object to which each regular expression match
> is passed. The return value is used as the filter's result in
> lieu of the matched text.
A Boost.Function object to which each regular expression match
is passed. The return value will be used in the filtered character
sequence in lieu of the matched text.
> "See Examples."
I'm not sure I see the problem. Maybe: See Examples (Regex OutputFilter).
> "The class templates basic_newline_filter is a DualUseFilter
> which converts between the text file formats used by...."
Why? I hope it's not "the superstition that 'between' can be used only of the
relationship between two things, and that if there are more 'among' is the right
preposition." (Fowler) :-)
> "Note: It is not known if specializations of basic_newline_filter
> other than basic_newline_filter<char> are useful. If not, the
> template parameter will be eliminated."
> Make this a footnote referenced from "Ch" in the Template
> Parameters section.
I wanted it to be prominent during the review. I'm planning to eliminate the
note and maybe the template parameter. Do you think it's necessary to use a
> Seward for making their excellent librarys available..."
at least I didn't say libaries. ;-)
> "...access to memory-mapped files on Windows an POSIX."
> "The memory-mapped file resources are based on work of Craig..."
> on the
Hmmm. Omitting the 'the' seemed more natural to me. To check common usage, I
tried the following Google query:
[ "on work of" indebted ]
and got this: http://tinyurl.com/4q82c. So I guess you're right. ;-)
> "Constructs...std::basic_filebuf buf opened as follows:"
I think 'buf' is residue from basic_filebuf and should be stricken.
> Generic Design
> "2. The library can be easily extended to handle..."
> can be extended easily (avoids split infinitive)
Where's the split infinitive? (Don't make me quote Fowler again ;-)
> Chain Interface
> "If there is a need for it, it can easily be restored."
> can be restored easily (avoids split infinitive)
> Planned Changes
> "2. The concept Buffered will be renamed MultiCharacter, since it
> is more descriptive and Buffered would be better used elsewhere."
> I don't understand this point. "MultiCharacter" does not convey
> anything useful. Even an unbuffered filter processes multiple
1. All filters, even those which do not model Buffered, use a buffer by default,
2. Bufered filters can be used without buffering, by specifying a buffer size
The real difference between Buffered filters and non-Buffered filters is that
the member functions of Buffered filters accept a *buffer* of characters:
read(Source&, char*, streamsize)
write(Sink&, const char*, streamsize)
This is why I think MultiCharacter is more descriptive. I'd like to use Buffered
for those resources which have their own internal buffers so that the library
won't automatically add an unnecessary layer of buffering.
> "4. ...This is necessary to accommodate i/o models just as..."
> Return Value
> "Returns a Resource...delimited by first and last."
> It is probably well understood by all readers, but it might be
> better to express this more formally.
> Broken link to
I can't find it.
> "This gives filters and resources an opportunity to free
> resources or reset their states in preparation for a fresh..."
Are you sure? "The
> When is close invoked?
> It is premature to discuss the invocations of close() without
> showing its synopsis. You should put the synopsis just after the
> Description section.
> streambuf_facade and stream_facade
> This section is a bit confusing. First you say that r.close()
> calls boost::io::close(r, std::ios_base::in) followed by
> boost::io::close(r, std::ios_base::out). Then, you say that if
> "r" controls a single sequence, those calls wind up, in effect at
> least, calling r.close().
This is wrong. Call the streambuf_facade instance 'sb'. Then calling sb.close()
causes boost::io::close(r, std::ios_base::in) and boost::io::close(r,
std::ios_base::out) to be called. These, in turn call r.close().
> filtering_streambuf and filtering_stream
> You used the term "complete" here. I recall it being defined
> elsewhere, but it would be useful if you had a single point of
> definition to which you could link whenever you mention it.
> The sequence of close() calls never mentions buf1. Is there a
> mistake? If not, some clarification is in order.
No, that's correct. buf1 only needs to be flushed using sync().
> "...each element receives two closure notifications..."
I agree that this should be rephrased to eliminate 'notifications', but I don't
think it's correct to say that an element receives calls.
> "The function template copy reads data from a given model of
> Source - or from a standard input stream or stream buffer - and
> writes it to a given model of Sink - or from a standard output
> stream or stream buffer - until the end of stream is reached."
> This sentence is confusing due to the number of hypenated
> phrases. If I've got it right, it should be written like this:
As I explained yesterday, I restored the status of standard streams and stream
buffers as full-fledged models of Resource, so the hypenated phrases can be
> "The size of the temporary buffer used may be supplied..."
> temporary buffer between the input and output streams
The size of the temporary buffer used for data transfer may be supplied.
> On many pages, "Description" is the topmost section. Here, it's
> a subsection of "Reference." Why? This section duplicates the
> information provided in the Overview, so one of them is
> superfluous. (This applies to many pages.)
Yes, I need to get this straight.
> Return Type
> If the return type is known to be "typename
> std::char_traits<typename char_type<Source>::type>::int_type" why
> not just show that as the return type in the synopsis?
Because it's ugly :-) How about [see below].
BTW, I'm considering changing the return type to allow it to represent three
types of cases:
1. a character was extracted
2. EOF was reached
3. No characters are surrently available -- try back later.
I think this is one of the most important interface issues -- what is your
> "The first overload.... The second overload...."
> No overloads have yet been shown, so this is premature. Move
> these sentences to Reference|Semantics.
I see your point, but I'd like this information up front. How about 'one
overload ... the other overload'?
> Template Parameters
> "T - For the first overload, a model of Source or a standard
> input stream or stream buffer type. For the second overload, a
> model of InputFilter."
> The fact that you must describe the parameter this way is a clear
> indication that you need to use better parameter names. How
> template<typename Resource>
> std::streamsize read(Resource& t, ...);
> template<typename InputFilter, typename Source>
> std::streamsize read(InputFilter& t, Source& src, ...);
> Since the definition of "Source" refers to T's character type,
> you'll have to make reference to Resource's or InputFilter's
> character type. With these distinctions in place, the subsequent
> Semantics sections won't need to replicate the declarations.
I think renaming the parameters is a good idea, but that recapping the synopsis
is also helpful.
> "The function template reverse takes a filter and returns a new
> filter which performs the same filtering operation as the
> original filter but which is an OutputFilter if the orginal
> filter was an InputFilter and and InputFilter if the orginal
> filter was an OutputFilter. Roughly speaking, it reverses the
> direction of a given filter."
> The ideas here are conveyed in the wrong order
in what way?
> and why, "roughly
Because I haven't formally defined the 'direction' of a filter.
> The function template reverse reverses the filtering direction
> of a given filter. It turns an InputFilter into an
> OutputFilter and an OutputFilter into an InputFilter.
> You mention memory overhead that can be a side effect of using
> reverse(). Are there performance issues as well?
As long as there's plenty of memory around, performance should be better than if
reverse weren't implemented in terms of one_step_filter.
> shouldn't that paragraph be set off with "Note:" or "Warning:"?
I like "Warning".
> You mention that using reverse may not be suitable for some data
> streams, but you need to give more guidance regarding why one
> would want to use reverse().
Okay. The reason is that you may have an implementation of a filtering algorithm
only as an output filter, but want to use the same algorithm for an input
filter. As I mentioned before, some algorithms are much easier to implement one
way than the other.
> Function Parameters
> "way - ..."
> You refer to std::ios_base::beg twice. The latter should be
> std::ios_base::end. Also, "way" would be better named "dir" or
> "direction," don't you think?
The standard uses 'off', 'way', 'which'.
> "The header <boost/io/categories.hpp> contains category tags for
> classifying models of the various filter and resource concepts."
> ^^^^^^ ^^^^^^^^
> Filter Resource
Here's a good place where lowercase seems clearly appropriate. Is Filter a
> "The header <boost/io/io_traits.hpp> contains the definitions of
> the metafunctions char_type and category, used to associate two
> fundamental types with each model of one the filter or resource
> I'm not quite sure how the end of that sentence should be
> phrased, but it's confusing as is. Perhaps this conveys the
> right information clearly:
> ...used to determine the type of characters processed by, and
> the category, or capability description, of Filters and
The header <boost/io/io_traits.hpp> contains the definitions of
the metafunctions char_type and category, which associate with
each model of Filter or Resource its character type and category.
> Character Type
> This section seems out of place. It should be titled,
> "char_type," but you haven't introduced that template yet. I
> suggest that this descriptive text be moved to the Class Template
> char_type|Description section.
> This section, too, is out of place. I suggest moving the content
> to Class Template category|Description.
Thanks. This page was a mess, but I wan't sure what to do with it.
> Where did this come from? I don't understand how io_traits::type
> is related to char_type (without looking at the code, of course).
This must be a holdover from the days when io_traits was a 'blob' representing
two metafunctions. Please point out where you see this, so I can eliminate it.
> Category Tags
> "...simply define a struct extending the existing tags."
> (multiply) derived from
"simply define a struct deriving from each of the existing tags using multiple
> The table doesn't which tags are mutually exclusive. Is that
> exclusivity enforced? For example, a type cannot be both a
> Filter and a Resource, so only one of filter_tag and resource_tag
> may be used to create a legitimate category. Is that enforced?
Categories are validated to a limited extent.
> Is a category tag validated in any way? That is, what if a
> developer specifies neither filter_tag nor resource_tag. Is the
> category tag still valid, will it produce a meaningful error, or
> will it wreak havoc?
You'll definitely get compiler errors, perhaps along the lines of
'filter_wrapper_impl<any_tag> has no member function read'. I guess I should
have a valid_category metafunction and use
> "Metafunction returning a mode tag corresponding the the mode of
> a model of one of the filter or resource concepts or of a
> standard stream or stream buffer."
> mode is a metafunction that determines the mode type that
> indicates the mode of the Filter or Resource. The mode can
> indicate whether the type is usable for input, output, or
> both, and whether and how the type supports seeking.
Good -- but how about
mode is a metafunction returning a tag structure
indicating the mode of a Filter or Resource. The mode
indicates whether the Filter or Resource is usable for
input, output, or both, and the type of seeking it supports,
> "Tr - The traits type"
> You should mention that std::char_traits<Ch> is the default for
> this parameter (it's in the synopsis, of course, but it bears
> You should also document which features of the
> traits class you need so folks that want to write their own can.
> (You might capture this information in one place to reference
> from multiple places.)
Surprisingly, perhaps, the traits type is really not needed. I'm assuming that
anyone who writes a new character type will also specialize std::char_traits (I
should say this). The traits template parameter is provided just so people can
construct streams and stream buffers with an alternate traits type, in case the
alternate traits type is required by some other API. It won't affect the
behavior of the stream or stream buffer.
For example, suppose there is an existing library that has a function of the
void f(std::basic_istream<japan_char, japan_traits>&);
If I didn't provide the traits parameter, instances of filtering_stream could
never be passed to this function.
> filtering_stream::filtering_stream (#4)
> The description leaves me wanting more. IIUC, this creates a
> complete filtering_stream with no Filters that uses an iterator
> based Resource. For input, that would mean that only the
> characters in the range [first, last) are read. For output, that
> would mean that characters are written through *first++ until
> first == last. If I've gotten that right, you need to say
> something like that so no one else must deduce the same
> information. Also, this filtering_stream would be complete,
> There's no parameter list introductory statement like, "The
> parameters have the following meaning." In fact, you've been
> inconsistent in this on many pages. However, adding a "Function
> Parameters" heading should be sufficient in and of itself.
> filtering_stream::push (#1)
> "t - An instance of T"
> Can you describe this better?
Given the detailed description of T, what more is needed?
> filtering_stream::push (#2)
> The signature of this function is identical to the previous push
> overload. Thus, you should merge the two in the synopsis and
> when documenting them.
The first takes a const reference, the second a non-const reference.
> "Clears the underlying chain. If the chain is initially complete,
> If I understand correctly, that should be worded more like this:
> If the chain was complete before calling reset, it closes and
> releases all Filters in the underlying chain. In either case,
> it closes and releases the Resource, if any.
The chain can't contain a Resource unless it's complete. So it should be
Clears the underlying chain. If the chain was complete before
calling reset, causes each filter and resource in the chain to be
closed using the function close.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk