|
Boost : |
From: William Kempf (sirwillard_at_[hidden])
Date: 2000-11-20 11:51:19
--- In boost_at_[hidden], Douglas Gregor <gregod_at_r...> wrote:
> On Mon, 20 Nov 2000 00:12:59 -0800
> Karl Nelson <kenelson_at_e...> wrote:
> > > More metaprogramming could yield more accurate error messages,
but VC++ has b
> > > ecome the limiting factor.
> >
> > VC++ is always a limiting factor. I had to jump through a hell
> > of a lot of huddles to get my code to work there and some of the
> > template formulations still cause random errors. I hope that
> > someday everyone here comes to realize how worthless that
> > sorry excuse for a compiler is and boycots it.
>
> This sentiment was expressed and discussed a few months ago (when
it was noted that VC++ 7.0 would be no better), but the overriding
concern seemed to be that several Boosters have to use VC++ at work,
and Boost would be of less value to them if they can't use it at
work. In any case - if I can get good error messages out of a real
compiler, I'll happily #ifdef out those portions for VC++.
VC++ *is* going to be a *lot* better, as the beta shows.
Unfortunately, "beter" doesn't include partial template
specialization, so it's still almost useless for a lot of template
meta programming, etc.
> > Speaking of lame compilers, not all compilers have void returns.
> > For those without it like VC++ you can use the int return trait
trick.
> > However, on others like SGI compiler this may fail. For SGI you
would
> > need to specialize callback<void,...> and all the implementations
> > using partial specialization.
>
> IMHO, using partial specialization is the better choice in any
case. I worry about the portability of the int casting trick.
I agree, though the specialization is problematic for our favorite
compiler.
> > (This is one of the things the really confused people in SigC,
there
> > are multiple formulations there to cover the bad case compilers.
It
> > makes for reams of code which just gets skipped on most
compilers.)
>
> After uploading the newest version of the callback library
yesterday I was lamenting the ugliness of the resulting code. As
careful as I was, the VC++ hacks have produced almost illegible
source from reasonably simple code.
It doesn't seem that bad to me (at least at the public interface
level... I've yet to look in the ::detail sub-namespace).
Unfortunately, portable code will often have ugly warts, and this is
made worse by non-conforming or buggy compilers. However, you've
done a good job of hiding the ugliness from the user.
> > So lets look at another minor issue. That is the virtuals
tables.
> > I benchmarked your callbacks against SigC 1.1 slots for binary
size.
> > I implemented 21 functors like this
> >
> > struct func_float_int_int
> > {
> > float operator()(int a, int b) { return float(a*b); }
> > };
> >
> > for combinations of float, int, and double. In then made one
> > callback for each functor, set it and called it. The
> > resulting binary was 430k debug and 30K striped. Most of the
space was
> > nothing but almost wothless typeinfo functions.
> >
> > 00000094 W boost::detail::functor_callback<func_int_int_int,
int, int, int, boost::detail::Unused> type_info function
> >
> > SigC 1.1 formulation on similar test was 90k debug and 17.4k
striped.
> > (done with static linking though much of is sharable in a
library)
> > This difference came because SigC didn't use the virtual table to
launch the
> > callback but instead a function pointer. However, I don't believe
> > a similar technique is possible in your code.
>
> I think this is an unfortunate cost of generality, and I don't see
how we can safely call operator() in an arbitrary functor without
type_info. Perhaps there is still sufficient magical energy in (type)
casting to make this work portably.
The "Hickey approach" does with out a v-table. Again, though, I'm
concerned about portability and haven't thought about how it would be
applied to general functors (he applies it only to function pointers
and "closures").
> > This raise the problem I expressed before, that if you use a
large
> > number of functor types it can eat a lot in binary size. It
doesn't
> > look to extreme for your library, but you should test with
> > reasonable numbers of callbacks and functors to see how much it
scales.
> > I only optomized SigC because gtk-- used several hundred which
> > would have added 2M to the library binary size in typeinfo and
> > similar stuff.
> >
> > Hope it helps.
>
> It does.
I'm still looking over your code. What I've seen so far looks
exactly like what I had in mind and seems to be well implemented.
After considering the differences between this and Slots we should
decide if one is better than the other, or if both are legitimate for
different purposes (the likely result, I think). Then, if callbacks
are considered useful instead of or in addition to Slots, I'd
recommend your code as the basis for finalizing the idea.
That said, I do have one comment/question about your code. Your
boost::callback class has several functions that operate on a
base_type (typedefed to the boost::detail template that is the bridge
class for external polymorphism). Why is this? I see nothing in the
implementation that would use them. If the implementation doesn't
use them they should not exist, because users should not be using
types from the detail namespace any way (even if they are typedefed
within the callback). If the implementation does use them then for
the same reason I'd think they should be private. Removal of them
would greatly simplify the interface.
Bill Kempf
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk