Boost logo

Boost :

From: Karl Nelson (kenelson_at_[hidden])
Date: 2001-12-27 19:07:58


[...]
> > > Is the C++ standard library a practical industrial library? I would say
> > > "yes", but I would not say that it is a "single library" at all. It is
> > > made up of many pieces - algorithms, function objects, data structures -
> > > all separate little libraries of their own that can be combined in
> > > powerful ways.
> >
> > This isn't true though. Streams library doesn't really play all that
> > nice with the strings library. None of the interfaces take strings
> > in native form.
>
> Streams also isn't at all a concept-based framework. I meant to exclude
> streams, so I should have said "C++ standard _template_ library."
>
> > Some people like Qt would likely argue that C++
> > standard library isn't practical for cross platform devel. Though
> > fortunately, I will give you that point as I generally thing it
> > reasonably useful.
>
> This is hardly a fault of the library itself, or the standard, but of
> implementors dragging their feet and users persisting in choosing compiler
> and library vendors that drag their feet.

I expact that certain implementers will never get their compilers
up to standards where most of this can be regular practice.

> > The point remains should they be a standard at this point. Is it
> > not entirely likely that there could be wildly different implementations.
> > Should not boost pick and choose once something gets to be industry
> > practice rather than trying to press something into industry practice
> > by introducing some piece as of a standard.
>
> How often is a new paradigm adopted as industry practice? I think STL is
> still our best example here - that was not industry practice, and still isn't
> industry practice, but it was accepted because it was a great leap forward in
> library design.

And becuase it provided what people felt was needed. I am still not
convinced a third of boost really is.

 
> > > I would think that greater importance would be placed on the question of
> > > how easily one can create new adaptors, and what pitfalls are inherent in
> > > the creation process.
> > >
> > > > You missed the point entirely. How is adaptor supposed to know
> > > > what method to pull out of functor? Does it simply implement
> > > > every operator()(....) for arguments 1 through 10?
> > >
> > > Yes, it's common practice amongst binding libraries.
> >
> > Then how sould such implementations choose the correct implementation
> > of a function when overloaded to references and constant references?
>
> I didn't say I liked the practice :)
> Seriously, the fact that there isn't a good way to create pass-through
> function objects without knowing the exact types of the arguments is a big
> problem. I believe that people are looking into core language fixes to make
> pass-through function objects possible.

That would help. Thus far C++ has been a continuous headache with
regard to pass through. It makes me wish they just had a meta
language for generating code (real code) on the fly.

 
> > A very old design of mine was trying such a trick to make a new-like
> > object. It simply passed the arguments to new T(....) and then
> > called a function on the pointer. The problem aways became that it
> > would choose the wrong function when overloading came.
>
> The only real problem is with non-const references. I, personally, have never
> run into the problem in practice.

I have and have suggested on mailling lists in the past that C++
should allow the construct...

  template <class T,class T1&,class T2&,class T3&>
  T* generate(T1 t1, T2 t2, T3 t3)
    { return new (my_pool) T(t1,t2,t3); }

Where T1 first tries a reference then a const reference, then on down the
chain of standard guesses.

Making a decent argument passing interface in C++ is very poor at
best.

 
> > > The first enables the advances in the area of functional composition to
> > > be immediately useful within a signals & slots framework. At some point
> > > one library will likely dominate the functional composition arena, and
> > > users will need to learn only one functional composition vocabulary that
> > > they can apply to standard algorithms, callbacks, signals & slot,
> > > semantic actions in parsing, etc. The vocabulary _must_ be the same for
> > > all types of libraries or
> > >
> > > we will not be serving the user's needs.
> >
> > I am not sure that can't already be done in the sigc++ design. Part of
> > the constraints that sigc++ work on todays compilers prevents much
> > exploration of that type of design. Though I do see that it should at some
> > point be worked in.
>
> Good, but why would you compromise a library's usability because of old,
> broken compilers? Perhaps it is helpful in the establishment of "existing
> practice" if every compiler can handle the code, but it also forces the
> "existing practice" to be behind the "best-known" practice.

Because I still do not believe that under the best of circumstances that
compilers will improve that much. I have been coding SigC++ for over
2 years and still have the same petty problems with most of the
compilers out there. This compiler doesn't like void returns, that
one doesn't like traits for references, this one does but doesn't use
them unless it is the first Tueday of the third week in May.
 

> > This portion is adaptable... After what difference is it to you if
> >
> > bind(foo, _1, 1) /* where foo can be anything */
> >
> > returns a functor2<int,int,int> (concrete type) or a
> > _bi::internal::bind_type< some_functiontype<int,int>, int,int.....>
> > (chain of abstract types.). Yes, it means that "good" adaptors
> > will have to be written to return the generic component. But at the
> > same time it controls the types the user needs to worry about.
>
> To return a function<int, int, int>, one needs to know the exact argument and
> return types of foo; this isn't so easy if foo is a function object with
> multiple operator()'s.

Then have the used do....
  template <class T>
  struct my_functor
  {
    typedef void return_type;
    typedef args<int,int> args_type;
    void operator()(int, int) {};
  }

> The difference, to me, is that returning a concrete
> type means two things: we're erasing type information (since the actual
> object that is called has a type that can't b exported through the
> function<int, int, int>) and we're going to pay a price in efficiency if we
> don't need the type erasure. bind(foo, _1, 1) passed directly to
> std::transform is more efficient if it does not return a concrete type; more
> flexible, too, with regard to multiple or templated operator()'s.

Multiple typed operator() with a callback is just plan evil. You
will never get a compiler to generate any sort of meaningful error
to the user with such a construct.

> If there is
> going to be type erasure at some point in the system (which there must be),
> do it as late as possible so we have the most chance to use the information.
 
> > > The second is merely for user customization and optimization. A fully
> > > general callback class is not necessary for all applications, and carries
> > > with it more overhead than a simple callback class (e.g., a function
> > > pointer).
> >
> > This point I disagree strongly on. The full general callback
> > which can be concretely typed and used universally, carries some
> > overhead, but that overhead caps out rather quickly in a large
> > program. Usually around 64 bytes of dynamic and a very small amount
> > of static. The peice meal approach will likely go well over that.
>
> Concrete typing has to exist at some point, of course. But to say that the
> overhead will be higher just because the concrete type itself is a template
> parameter is misguided. What's the real difference between
> std::list<my_callback_type> and std::list<your_callback_type> if
> my_callback_type and your_callback_type are roughly equivalent in efficiency
> and size?

If every one of your types potentially has a different adaptor sets
and those types must be exposed then there is a huge difference, mine
compiles!

You continue to gloss the issue that a concrete type library is needed
in that you can not declare a

  template <class T> virtual void connect(const T& t);

But really, if a concrete signal/slot is not what boost needs, then
I will happily go back to my coding and bid this venture goodbye.

--Karl


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