[review] Formal Fast-Track review of the Boost.Functional/Factory library - extended until sunday

Hi all, I've extended the review until Sunday (inclusive). I'm hoping for more reviews. So far, we've had only two. If you are interested in the library (you should be :)), please take some time to review it. This is the info you need to do a review on: *Description* Factories are callback mechanisms for constructors, so we provide two function objects, boost::value_factory and boost::factory, that encasulate object construction through direct application of the constructor or operator new, respectively. These templates make other facilities that operate on function objects (such as standard algorithms, Boost.Bind, Boost.Function, or Fusion functional adapters) applicable to constructors. *Author* Tobias Schwinger *Download* Get it from here: http://www.boost-consulting.com/vault/index.php?action=downloadfile&filename=factory.zip&directory=X-Files& Read documentation online here: http://torjo.com/tobias/ What to include in Review Comments ================================== Your comments may be brief or lengthy, but basically the Review Manager needs your evaluation of the library. If you identify problems along the way, please note if they are minor, serious, or showstoppers. Here are some questions you might want to answer in your review: * What is your evaluation of the design? * What is your evaluation of the implementation? * What is your evaluation of the documentation? * What is your evaluation of the potential usefulness of the library? * Did you try to use the library? With what compiler? Did you have any problems? * How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? * Are you knowledgeable about the problem domain? And finally, every review should answer this question: * Do you think the library should be accepted as a Boost library? Be sure to say this explicitly so that your other comments don't obscure your overall opinion. Best, John Torjo - Review Manager - -- http://John.Torjo.com -- C++ expert ... call me only if you want things done right

Just a quick note, and sorry that I haven't reviewed the library yet: When doing a *fast-track* review, it would be helpful to note which Boost components already use the library, and in what form.

Peter Dimov wrote:
Just a quick note, and sorry that I haven't reviewed the library yet:
When doing a *fast-track* review, it would be helpful to note which Boost components already use the library, and in what form.
Unlike the former, this one's not a factorization. That list under http://www.boost.org/more/formal_review_process.htm#Fast-Track isn't meant to be AND-reduced, is it? Anyway, it was the Wizard's suggestion (I originally asked for a single, collective review for all the tiny bits and pieces), so I figure it'll be OR. Regards, Tobias

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Friday 21 December 2007 07:33 am, John Torjo wrote:
Read documentation online here: http://torjo.com/tobias/
There seems to be a typo in the documentation for value_factory, in the notation where it says: F the type value_factory<F> I think it's supposed to be value_factory<T> - -- Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFHa/4K5vihyNWuA4URAj4lAJ9E02D1esP2ly2OstzXPhBtJ1ZJuACfQReJ 5pLUP+2mxp4Y3SNrGyoHWuo= =lAs6 -----END PGP SIGNATURE-----

Frank Mori Hess wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Friday 21 December 2007 07:33 am, John Torjo wrote:
Read documentation online here: http://torjo.com/tobias/
There seems to be a typo in the documentation for value_factory, in the notation where it says:
F the type value_factory<F>
I think it's supposed to be value_factory<T>
Yep. Thanks, Tobias

John Torjo wrote:
Hi all,
I've extended the review until Sunday (inclusive). I'm hoping for more reviews. So far, we've had only two. If you are interested in the library (you should be :)), please take some time to review it. This is the info you need to do a review on:
*Description*
Factories are callback mechanisms for constructors, so we provide two function objects, boost::value_factory and boost::factory, that encasulate object construction through direct application of the constructor or operator new, respectively. These templates make other facilities that operate on function objects (such as standard algorithms, Boost.Bind, Boost.Function, or Fusion functional adapters) applicable to constructors.
Is there any difference to lambda::constructor/new_ptr? Regards, -- Shunsuke Sogame

shunsuke wrote:
John Torjo wrote:
Hi all,
I've extended the review until Sunday (inclusive). I'm hoping for more reviews. So far, we've had only two. If you are interested in the library (you should be :)), please take some time to review it. This is the info you need to do a review on:
*Description*
Factories are callback mechanisms for constructors, so we provide two function objects, boost::value_factory and boost::factory, that encasulate object construction through direct application of the constructor or operator new, respectively. These templates make other facilities that operate on function objects (such as standard algorithms, Boost.Bind, Boost.Function, or Fusion functional adapters) applicable to constructors.
Is there any difference to lambda::constructor/new_ptr?
Yes, those components are designed to only work with the Lambda library. Functional/Factory OTOH provides standard compliant (they work with result_of and the libraries built upon it) function objects. Regards, Tobias

On Dec 21, 2007 5:33 AM, John Torjo <john.groups@torjo.com> wrote:
What to include in Review Comments ==================================
* What is your evaluation of the design?
Nice and clean. One complaint: Allocator should be inherited :-) OK, in general, here is a case for supporting inheritance in all of these adapter classes. As an exercise, I wanted to make a factory that will do two things - one, provide perfect forwarding; and two - count the number of objects that have been created by the factory. This is what I came up with: template<typename T, typename Allocator=std::allocator<void> > struct counting_factory : private boost::factory<T, Allocator> { counting_factory() : count() {} using counting_factory::result_type; template<typename Sequence> typename counting_factory::result_type operator()(const Sequence &s) { count++; return boost::fusion::fused<boost::factory<T, Allocator> >()(s); } int count; }; template<typename T, typename Allocator=std::allocator<void> > struct perfect_factory : public boost::forward_adapter< boost::fusion::unfused_lvalue_args< counting_factory<T, Allocator> > > {}; There are two problems. One - I can't dig out the count, because it's buried in private membership with no access functions to let me get to it. Two - the size of the resulting perfect_factory is 8 (GCC 4.0.1/darwin), and as far as I can tell the only thing in this entire chain of inheritance that needs storage space is `int count`. Maybe there is a simple way to do what I set out to do without running into the above problems, in which case I'd like to know about it. Otherwise, I would jump with joy if all of these adapters used *protected* inheritance so I could also dig up parts of an inherited class's interface (say, counting_factory above could have a public method get_count, which I could expose as public in the perfect_factory).
* What is your evaluation of the implementation?
Didn't see any problems with this one. But, in testing it I think I found that forward_adapter.hpp needs a #undef BOOST_PP_INDIRECT_SELF
* What is your evaluation of the documentation?
When I first gave this one a try, I skimmed through the docs and didn't realize that * factory wants a pointer type as the template paramater * the pointer can be a smart pointer (this is really cool) Of course, it's all there, but to help people like me that like to skim maybe separate the the two templates (factory and value_factory) a little bit more in the introduction so that it reinforces that they are different in usage. Also, the usefulness of the library is described in "These templates make other facilities that operate on function objects (such as standard algorithms, Boost.Bind, Boost.Function, or Fusion functional adapters) applicable to constructors". There is a small example below showing how it can be used with Boost.Function - it would be great to give some more examples involving bind or fusion adapters, as it would really help users see what all can be done using this. The synopsis for factory doesn't mention the Allocator template parameter... in fact I'm not sure whether this is discussed anywhere.
* What is your evaluation of the potential usefulness of the library?
I can see it being very useful.
* Did you try to use the library? With what compiler?
Yes, GCC 4.0.1/darwin.
Did you have any problems?
Nope
* How much effort did you put into your evaluation? A glance? A quick reading? In-depth study?
I skimmed the docs, looked at the code, tried using it a little, re-read the docs, then played with the example I mentioned above.
* Are you knowledgeable about the problem domain?
I recently found a need for something like this, but otherwise no.
And finally, every review should answer this question:
* Do you think the library should be accepted as a Boost library? Be sure to say this explicitly so that your other comments don't obscure your overall opinion.
Yes, assuming this isn't covered in boost already (Shunsuke Sogame raised an interesting question in regards with lambda::constructor/new_ptr. AFAICT, it does appear similar to factory, but I'm not sure that new_ptr supports custom Allocators or smart pointers (I only gave it a brief look). What about value_factory<T> and constructor<T>, though?) Stjepan

On Dec 21, 2007 12:31 PM, Stjepan Rajko <stipe@asu.edu> wrote:
Otherwise, I would jump with joy if all of these adapters used *protected* inheritance so I could also dig up parts of an inherited class's interface (say, counting_factory above could have a public
Hmm... I'm not sure that I know exactly what I'm talking about when insisting the inheritance should be *protected*... maybe just ignore it ... serves me right for bolding something like that :-) But this did make me think about whether using compressed_pair is the right thing to do, because maybe there are cases where things would be useful as inherited even when the base class is not empty. Stjepan

Hi Stjepan, thanks a lot for your both detailed and positive review! Stjepan Rajko wrote:
On Dec 21, 2007 5:33 AM, John Torjo <john.groups@torjo.com> wrote:
What to include in Review Comments ==================================
* What is your evaluation of the design?
Nice and clean. One complaint: Allocator should be inherited :-)
Yes, that's a very good point (much more than with Forward, IMO). However, I intentionally left support for custom Allocators undocumented to see whether someone would miss it. It doesn't really feel right to me and I'm tempted to throw it out again: If we use a custom Allocator we'll also need a custom Smart Pointer that uses this Allocator. None of our Boost Smart Pointers support Allocators and the Factory should actually initialize a stateful Allocator within a Smart Pointer that does. Overloading 'new' as a static member function seems the better way to go and one can write a template that does it inheriting an arbitrary class.
* What is your evaluation of the implementation?
Didn't see any problems with this one. But, in testing it I think I found that forward_adapter.hpp needs a #undef BOOST_PP_INDIRECT_SELF
Thanks for spotting this one!
* What is your evaluation of the documentation?
When I first gave this one a try, I skimmed through the docs and didn't realize that
* factory wants a pointer type as the template paramater * the pointer can be a smart pointer (this is really cool)
Of course, it's all there, but to help people like me that like to skim maybe separate the the two templates (factory and value_factory) a little bit more in the introduction so that it reinforces that they are different in usage.
OK.
Also, the usefulness of the library is described in "These templates make other facilities that operate on function objects (such as standard algorithms, Boost.Bind, Boost.Function, or Fusion functional adapters) applicable to constructors". There is a small example below showing how it can be used with Boost.Function - it would be great to give some more examples involving bind or fusion adapters, as it would really help users see what all can be done using this.
Yes, I figured this would be helpful answering Nat Goodspeed's review.
The synopsis for factory doesn't mention the Allocator template parameter... in fact I'm not sure whether this is discussed anywhere.
See above.
* Do you think the library should be accepted as a Boost library? Be sure to say this explicitly so that your other comments don't obscure your overall opinion.
Yes, assuming this isn't covered in boost already (Shunsuke Sogame raised an interesting question in regards with lambda::constructor/new_ptr. AFAICT, it does appear similar to factory, but I'm not sure that new_ptr supports custom Allocators or smart pointers (I only gave it a brief look). What about value_factory<T> and constructor<T>, though?)
See answer to Shunsuke's post. Regards, Tobias

Hello John Torjo, I don't know where to send my review of Boost.Factory library - therefore i send it to you. I hope, that until my next review i know it better, but today i must answer before the time to review has gone.
* What is your evaluation of the design? * What is your evaluation of the implementation?
I like, that the lib has direct support for smart pointer, because this is a normal technic in C++. But i often has the problem of a 2 phase initialisation. I don't like it, but i found it very often in practice. After the constructor for example i must call an init function. Or sometimes i must do things which are not possible in a constructor. I would like, if the factory would support such mechanism. I would like a third (or better an second template argument, and the allocator become the third argument), which is a policy class for the two phase construction. After the new the factory call a static function in the policy class. Default policy is a class which does nothing. But here I can write a class, which calls e.g. a init function or other things. Second I would like a name like factory_ptr or factory_pointer more than only factory for the class. It shows more whats the problem domain of the factory, and stands more in parallel to factory_value.
* What is your evaluation of the documentation?
I would like a better motivation. I have discuss the lib with a friend to understand why I need such a lib. I think, not everybody (I include) has a deep understanding of modern C++ technics, and therefore a better motivation with two more detailed examples would help the beginners.
* What is your evaluation of the potential usefulness of the library?
I think, the lib addresses a seldom problem. That's why I need some time to understand the motivation. Perhaps it is a normal problem if the user has more knowlegde about all STL and Boost libs. But I love it, if there is a "standard" way of doing things, because it makes the code more readable. Therefore I like small libs for not often problems too. I could solve the problem every time with some small functions without a lib, but with the lib I don't need this small code, and my code becomes more readable.
* Did you try to use the library? With what compiler? Did you have any problems?
I have make some little examples and compiles them with the Microsoft Visual Studio 2003 (MSV 7.1) without any problems.
* How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? * Are you knowledgeable about the problem domain?
I have taken 2 hours to read the documentation, to study the header and the implemenation and to play with some examples.
And finally, every review should answer this question:
* Do you think the library should be accepted as a Boost library?
Yes. I think the library should accepted to Boost, but with the three discussed extensions: - Better name for factory: factory_ptr or factory_pointer. - Better motivation for beginners in the docu. - Extension with a third template parameter for e.g. 2 phase construcion. Greetings Detlef Wilkening -- http://John.Torjo.com -- C++ expert ... call me only if you want things done right

On Mon, Dec 24, 2007 at 02:41:06AM +0200, John Torjo wrote:
Hello John Torjo,
Oops, this mail confused me! It was probably not written by John, even if the FROM: line says so but from:
Greetings
Detlef Wilkening
Detlef, don't fake your mails! Jens

On 12/24/07, Jens Seidel <jensseidel@users.sf.net> wrote:
On Mon, Dec 24, 2007 at 02:41:06AM +0200, John Torjo wrote:
Hello John Torjo,
Oops, this mail confused me! It was probably not written by John, even if the FROM: line says so but from:
Greetings
Detlef Wilkening
Detlef, don't fake your mails!
It is likely that John Torjo received the email privately and forwarded it to the mailing list, and forgot to add a notice. gpd

Giovanni Piero Deretta wrote:
On 12/24/07, Jens Seidel <jensseidel@users.sf.net> wrote:
On Mon, Dec 24, 2007 at 02:41:06AM +0200, John Torjo wrote:
Hello John Torjo,
Oops, this mail confused me! It was probably not written by John, even if the FROM: line says so but from:
Greetings
Detlef Wilkening
Detlef, don't fake your mails!
It is likely that John Torjo received the email privately and forwarded it to the mailing list, and forgot to add a notice.
Yes, I got this message privately. But in the subject of the email says "on behalf of Detlef Wilkening". Best, John -- http://John.Torjo.com -- C++ expert ... call me only if you want things done right

Hello! John Torjo wrote:
Hello John Torjo,
I don't know where to send my review of Boost.Factory library - therefore i send it to you. I hope, that until my next review i know it better, but today i must answer before the time to review has gone.
* What is your evaluation of the design? * What is your evaluation of the implementation?
I like, that the lib has direct support for smart pointer, because this is a normal technic in C++.
But i often has the problem of a 2 phase initialisation. I don't like it, but i found it very often in practice. After the constructor for example i must call an init function. Or sometimes i must do things which are not possible in a constructor. I would like, if the factory would support such mechanism.
I would like a third (or better an second template argument, and the allocator become the third argument), which is a policy class for the two phase construction. After the new the factory call a static function in the policy class. Default policy is a class which does nothing. But here I can write a class, which calls e.g. a init function or other things.
Honestly, I think that RAII is almost always the right design. I believe that "two phase construction" is often just bad practice (at least if we can use exceptions). So if for some reason we can't get around using "two phase construction" it can (and should) be done in user code: The Factory utility is about turning a new expression or constructor into a functional - nothing more as beyond that thing are sufficiently trivial to implement (given other Boost tools, that is) and vary greatly on a per-use-case-basis. Once the constructor is run you can use a virtual function to invoke the second phase: class A { public: virtual void init() = 0; virtual void foo() = 0; // ... }; class B : public A { public: B() { cout << "B::B" << endl; } void init() { cout << "B::init" << endl; } void foo() { cout << "B:foo" << endl; } }; // ... map<string,function<A*()> > factory_registry; int main() { factory_registry["B"] = factory<B*>(); //... A* a1 = factory_registry["B"](); a1->init(); // ... delete a1; return 0; }
Second I would like a name like factory_ptr or factory_pointer more than only factory for the class. It shows more whats the problem domain of the factory, and stands more in parallel to factory_value.
I disagree - it's just confusing :-) as one might conclude the factory itself for being a smart pointer or being applicable only to pointers. A similar argumentation applies to "factory_value".
* What is your evaluation of the documentation?
I would like a better motivation. I have discuss the lib with a friend to understand why I need such a lib. I think, not everybody (I include) has a deep understanding of modern C++ technics, and therefore a better motivation with two more detailed examples would help the beginners.
Yes. I'll add two more complete examples. Thanks for your review! Regards, Tobias
participants (8)
-
Frank Mori Hess
-
Giovanni Piero Deretta
-
Jens Seidel
-
John Torjo
-
Peter Dimov
-
shunsuke
-
Stjepan Rajko
-
Tobias Schwinger