Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2002-10-19 23:01:52


Just reading through the Signals docs here, and came across a strange
use of the term "named template parameter":

        boost::signal<float (float x, float y),
                      maximum<float> > sig;

This is supposed to be a use of named template parameters to pass
maximim<float> to the signal class. Where's the "named parameter?"
This doesn't look anything like NTP as we've seen, e.g., in the
iterator adaptors library.

--
Also, I was wondering about the iterators which get passed to
combiners. I can imagine two ways this could work:
   1. The signal builds a sequence of return values, and then passes
      iterators to the sequence into the combiner.
   2. The signal builds iterators which invoke the slots lazily. The
      upshot is that the if the combiner stops looking at the
      sequence partway through, only a subset of the slots get called.
The tutorial docs don't mention which model gets used. Ah, if I dig
into the reference docs I can see that it's the 2nd model. Well, I
think the tutorial should mention this.
--
Also, various of the Signals doc pages incorrectly use the word
"Rational" where "Rationale" should appear.
--
Also also, the description of "preferred" and "compatible" syntaxes
fails to make it clear that the compatibile syntax works on all of the
compilers listed. I think it's important that people who want to write
portable code don't think they have to litter their code with #ifdefs
just to use this library.
--
It also says 
    "At this time there is a significant limitation to the use of
    trackable objects in making slot connections: function objects
    built using Boost.Bind are understood, so that any place a
    trackable object appears in a bind expression."
Isn't there a conclusion missing from this sentence?
And I think you should be careful about exactly what you write. I
think there are lots of ways a trackable object can "appear in a bind
expression" yet still be effectively hidden from bind, e.g.:
   bind(bind1st(f, x), y)
And what about references to trackable objects? If I build a bind
expression around ref(x), will it still be tracked?
--
In the section on "Passing Slots" it says "any valid function object
can be passed to a slot_type parameter". Do you mean "any _compatible_
function object", using the definition of compatible from the function
library?
Also, the example ought to demonstrate some valid/compatible function
object being passed to a slot_type parameter.
--
The formal docs for disconnect read:
   "Complexity: O(lg n) + k where n is the number of slots known to
   the signal and k is the number of ."
                                    ^
I think something is missing here---+
--
The "Signal Invocation" docs say:
   "Effects: invokes the combiner with a slot_call_iterator range
   [first, last) (i.e., combiner(first, last)) that iterates over the
   results of calling each slot with the given set of parameters a1,
   a2, ..., aN."
An iterator range doesn't iterate. Maybe you should say "...whose
values are the results of calling..." You should also mention that
if the iterator stops early, only a subset of the slots will be
called. Also you should specify whether it's incrementing or
dereferencing of the iterator which causes a slot call. 
Finally, the number of crazy font changes in this passage make it hard
to read. Maybe it'd work better if all of this material were not
italicized. Italics don't add much when used in bulk. In fact, it
looks like this problem is due to a missing </i> tag in the previous
section with the missing text.
--
The formal documentation for trackable really needs to make it clear
that special knowledge is required in the binder used and that only
Boost.Bind currently has that knowledge.
--
the docs for last_value<T> and its void specialization are confusing,
since we list two identical member function declarations with
different semantics. We should do something to mark the second one as
the void specialization.
--
The docs don't make it clear that visit_each is being called without
qualification, nor do they say which boost functions call it. Both of
those features are important for any point-of-customization that may
use Koenig lookup. Also, I realize that with existing compilers, we
have to rely on overloading in the user's namespace for this function,
but some consideration ought to be given to whether a
partially-specializable static member function wrapper wouldn't be the
better long-term solution for this case.
--
In the design document we mention Type erasure. I misread that about
ten times as describing a type called Erasure. I think starting the
first sentence of that section with "Type erasure" in quotes would
help a lot.
We also refer to "slot names", which confused me. I think we really
mean "slot group names" here, since individual slots aren't named. I'd
actually prefer if "name" was replaced with "identifier" or "id"
throughout the docs, since "name" really suggests a string.
-- 
rationale:
    "but in this case the original specification ties the
     implementation to the use of virtual functions internally."
This is unclear. Instead of saying "in this case the original
specification..." why don't we say "this arrangement still..."?  And
something should be said about why it's a bad thing to tie the
implementation to the use of virtual functions. Most people don't
think twice about using virtual functions, and are never sorry about
it.
    "uses a set of well-defined interfaces to discover information
    about the composition of arbitrary function objects."
Well, let's not oversell it. We can't really do that for arbitrary
function objects unless visit_each has been suitably defined, can we?
And, while I'm able to imagine the relationship this statement might
have to the rest of the paragraph, it's not very clear. We should
spell out that using primitives makes it easy for the library to track
lifetimes of function object elements.
The last sentence in the "pass slot to disconnect" section is a major
run-on. I'm having trouble figuring out what it's supposed to mean.
    "This type of interface is supported in Boost.Signals via the
    named connections mechanism"
As they say in the movies, "What the...?" Is this mechanism documented
anywhere?
   "The "push" model, on the other hand, relies on an interface
   specific to the caller and is generally reusable."
"not"?--------------------------^
   "the connection syntax supplied by Boost.Signals is no less
   powerful that than supplied by the signal."
What signal?
--
Must trackable be a public base, or is a private base OK? Can we have
an example of its use? OK, there's one in CVS. How about some links
from the docs to these examples?
--
I'm still wondering, after reading the docs, whether it's OK to send a
signal which ultimately destroys the signal itself.
--
This line in libs/signal/example/first_positive.hpp seems to rely on
unspecified behavior to match its comment, since none of the slots are
members of a named group.
  assert(sig_positive(3, -5) == 8); // returns 8, but prints nothing
--
                    David Abrahams
dave_at_[hidden] * http://www.boost-consulting.com
-- 
                    David Abrahams
dave_at_[hidden] * http://www.boost-consulting.com
Building C/C++ Extensions for Python: Dec 9-11, Austin, TX
http://www.enthought.com/training/building_extensions.html

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