
Dear Boost community, do we have a function object template to wrap arbitrary constructor calls / operator new expressions somewhere in Boost, already? If not, is there any interest in such a thing? Interface draft: ================ factory<T> // constructs X and returns it by value factory<T*> // uses operator new, returns a pointer Where operator() takes a variable number of arguments, forwarded to the constructor. Should there be an optional 'Allocator' template parameter? Some use cases: =============== o Transform through an explicit constructor, e.g: std::transform(from,to,out,factory<X>()); or a constructor that takes more than one argument, e.g: std::transform(from,to,out, boost::bind(factory<Y>(),12,_1)); o Generate data, e.g: std::generate_n(out,12,boost::bind(factory<Y>(),123,12)); o Creating homogeneous, polymorphic factories from heterogeneous constructors, e.g: void register_factory( std::type_info const &, boost::function<void*()> const &); // ... at function scope: register_factory( typeid(X), factory<X>() ); register_factory( typeid(Y), boost::bind(factory<Y>(),12,1) ); Implementation notes regarding the Forwarding Problem: ====================================================== For now (C++89) it might be good enough to just have operator() take its arguments by non-const reference. As usually the call will be deferred and as long as the arguments are L-Values they will be deduced even if const qualified (this might break the code of the first use case above - wrapping the factory specialization into a Boost.Bind function object without actually binding anything will work around the problem, though). Alternatively we could solve the forwarding problem (within the function object itself) using a "hammer and crowbar utility" in Fusion (overloading operator() with all combinations of templatized const/non-const reference parameters) until we have better means to do so. I personally prefer the former because it's more lightweight and might allow us to be more portable than Fusion is, however. Curiously awaiting your feedback, Tobias

Hi Tobias, On 17/06/07, Tobias Schwinger <tschwinger@isonews2.com> wrote:
Dear Boost community,
do we have a function object template to wrap arbitrary constructor calls / operator new expressions somewhere in Boost, already?
If not, is there any interest in such a thing?
Normally when I need a generic Factory facility, I turn to the Loki library. However, some of the use cases that you describe aren't really possible with this, so I'd say yes, I'd be interested. Regards, Glyn

Tobias Schwinger wrote: [1]
For now (C++89) it might be good enough to just have operator() take its arguments by non-const reference. As usually the call will be deferred and as long as the arguments are L-Values they will be deduced even if const qualified (this might break the code of the first use case above - wrapping the factory specialization into a Boost.Bind function object without actually binding anything will work around the problem, though).
[2]
Alternatively we could solve the forwarding problem (within the function object itself) using a "hammer and crowbar utility" in Fusion (overloading operator() with all combinations of templatized const/non-const reference parameters) until we have better means to do so. I personally prefer the former because it's more lightweight and might allow us to be more portable than Fusion is, however.
Have [2] for a predefined limit (say 3) and do the rest [1] for more (e.g. 3 or more). Isn't that how you did it with the fusion functional stuff? Anyway, yeah, I need such a utility, especially if it is lighweight. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

Hi Joel, Joel de Guzman wrote:
Tobias Schwinger wrote:
[1]
For now (C++89) it might be good enough to just have operator() take its arguments by non-const reference. As usually the call will be deferred and as long as the arguments are L-Values they will be deduced even if const qualified (this might break the code of the first use case above - wrapping the factory specialization into a Boost.Bind function object without actually binding anything will work around the problem, though).
[2]
Alternatively we could solve the forwarding problem (within the function object itself) using a "hammer and crowbar utility" in Fusion (overloading operator() with all combinations of templatized const/non-const reference parameters) until we have better means to do so. I personally prefer the former because it's more lightweight and might allow us to be more portable than Fusion is, however.
...and avoids circular dependencies if placed outside of and used by Fusion.
Have [2] for a predefined limit (say 3) and do the rest [1] for more (e.g. 3 or more).
The first two will probably do, since AFAIK both standard and Fusion algorithms will be happy with it. OTOH, once there's a single "L/R-Value overload", users will probably request more of them for manual use (which could be an argument not to add them in the first place).
Isn't that how you did it with the fusion functional stuff?
Well, unintentionally - it was a bug, not a feature :-|. It has recently been fixed (upon Eric Niebler's report) and now there are overloads for all combinations for (default-wise) 6 parameters, now.
Anyway, yeah, I need such a utility, especially if it is lightweight.
Wonderful (what a coincidence)! In fact, the recent discussion of a "fused_ctor" brought it up and the utility also fits nicely into the "Fusion infinity puzzle" (to be continued). It seems misplaced in Fusion, however, because it is generally useful without having anything to do with tuples. Ideally the idea or even the implementation (that is, I'd provide one if there's interest) gets adopted by the utility suite of an existing library (such as Bind) or integrated into an existing set of utilities (e.g. In-Place - which would become Factory then). Otherwise we'd have an "ultra fast track candidate" for boost/utility which would live in Fusion until it finds a better home. Regards, Tobias

Tobias Schwinger wrote:
Dear Boost community,
do we have a function object template to wrap arbitrary constructor calls / operator new expressions somewhere in Boost, already?
Yes, it's in_place. Used by optional, for example. For some reason though it seems there is no definition for default constructors, but that can be added trivially.

Mathias Gaunard wrote:
Tobias Schwinger wrote:
Dear Boost community,
do we have a function object template to wrap arbitrary constructor calls / operator new expressions somewhere in Boost, already?
Yes, it's in_place.
Well, that's not quite the same: The in_place stuff deals with in-place construction (hence the name), which is a different pair of shoes. It's not applicable to the use cases outlined in my previous post, since it doesn't (and probably wouldn't make sense to) provide a function object interface (since it has to know the memory location where the object should be constructed). Regards, Tobias

Marcus Lindblom wrote:
Tobias Schwinger wrote:
Dear Boost community,
do we have a function object template to wrap arbitrary constructor calls / operator new expressions somewhere in Boost, already?
lambda::new_ptr ?
Yep, 'new_ptr' and 'constructor' are almost exactly what I want. Those templates are missing a 'result_type' typedef to become usable as "stand-alone function objects" (outside of Boost.Lambda expressions). Further, the limits are a bit too low for constructing Fusion Sequences and having them configurable would be nice to have, too... Thanks, Tobias

Tobias Schwinger wrote:
Marcus Lindblom wrote:
Tobias Schwinger wrote:
Dear Boost community,
do we have a function object template to wrap arbitrary constructor calls / operator new expressions somewhere in Boost, already?
lambda::new_ptr ?
Yep, 'new_ptr' and 'constructor' are almost exactly what I want.
Those templates are missing a 'result_type' typedef to become usable as "stand-alone function objects" (outside of Boost.Lambda expressions).
Further, the limits are a bit too low for constructing Fusion Sequences and having them configurable would be nice to have, too...
Yes and IMO these things should be called new_ and construct. -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler wrote:
Tobias Schwinger wrote:
Marcus Lindblom wrote:
Tobias Schwinger wrote:
Dear Boost community,
do we have a function object template to wrap arbitrary constructor calls / operator new expressions somewhere in Boost, already?
lambda::new_ptr ? Yep, 'new_ptr' and 'constructor' are almost exactly what I want.
Those templates are missing a 'result_type' typedef to become usable as "stand-alone function objects" (outside of Boost.Lambda expressions).
Further, the limits are a bit too low for constructing Fusion Sequences and having them configurable would be nice to have, too...
Yes and IMO these things should be called new_ and construct.
Yep, 'new_ptr' is sorta strange ;-). I'm not too convinced that 'construct' gives a better name than 'constructor', because looking at construct<T>() I get the impression that something gets constructed, but in reality it's just about capturing T's constructor in order to pass it around. Regards, Tobias

Tobias Schwinger wrote:
Eric Niebler wrote:
Tobias Schwinger wrote:
Marcus Lindblom wrote:
Tobias Schwinger wrote:
Dear Boost community,
do we have a function object template to wrap arbitrary constructor calls / operator new expressions somewhere in Boost, already?
lambda::new_ptr ? Yep, 'new_ptr' and 'constructor' are almost exactly what I want.
Those templates are missing a 'result_type' typedef to become usable as "stand-alone function objects" (outside of Boost.Lambda expressions).
Further, the limits are a bit too low for constructing Fusion Sequences and having them configurable would be nice to have, too... Yes and IMO these things should be called new_ and construct.
Yep, 'new_ptr' is sorta strange ;-).
I'm not too convinced that 'construct' gives a better name than 'constructor', because looking at
construct<T>()
I get the impression that something gets constructed, but in reality it's just about capturing T's constructor in order to pass it around.
So what? They're just lazy! I second Eric. "new_" and "construct" are better names. Subjective, nonetheless, but that's how it's spelled in Phoenix (ahem :) ahem). So, do I change all the names because phoenix functions are lazy? Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

Joel de Guzman wrote:
Tobias Schwinger wrote:
I'm not too convinced that 'construct' gives a better name than 'constructor', because looking at
construct<T>()
I get the impression that something gets constructed, but in reality it's just about capturing T's constructor in order to pass it around.
So what? They're just lazy!
I second Eric. "new_" and "construct" are better names. Subjective, nonetheless, but that's how it's spelled in Phoenix (ahem :) ahem). So, do I change all the names because phoenix functions are lazy?
Phoenix is lazy per-se, so imperative names are perfectly OK for that library. For some general utility I'd prefer to emphasize the laziness. So what's wrong with 'factory' in the first place? Anyway, can those Phoenix tools be used as standard function objects (with support for 'boost::result_of')? If so, it's probably not worth the trouble writing something new... Regards, Tobias

on Sun Jun 17 2007, Tobias Schwinger <tschwinger-AT-isonews2.com> wrote:
Dear Boost community,
do we have a function object template to wrap arbitrary constructor calls / operator new expressions somewhere in Boost, already?
If not, is there any interest in such a thing?
Interface draft: ================
factory<T> // constructs X and returns it by value factory<T*> // uses operator new, returns a pointer
auto_ptr, please.
Where operator() takes a variable number of arguments, forwarded to the constructor.
Isn't in-place construction the most general case? -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

David Abrahams wrote:
on Sun Jun 17 2007, Tobias Schwinger <tschwinger-AT-isonews2.com> wrote:
Interface draft: ================
factory<T> // constructs X and returns it by value factory<T*> // uses operator new, returns a pointer
auto_ptr, please.
Generic algorithms won't 'get' it. In this light, it seems better to have a separate template for pointers, so you clients can specify what they want, explicitly: new_< T* > new_< auto_ptr<T> > new_< special_smartie<T> > (Seems tricky to deduce T but it might be doable).
Where operator() takes a variable number of arguments, forwarded to the constructor.
Isn't in-place construction the most general case?
It sure is, but not necessarily the most handy. How to tell e.g. std::transform to allocate memory for the transformed elements? Not sure I really got your point, here. Regards, Tobias

on Tue Jun 19 2007, Tobias Schwinger <tschwinger-AT-isonews2.com> wrote:
David Abrahams wrote:
on Sun Jun 17 2007, Tobias Schwinger <tschwinger-AT-isonews2.com> wrote:
Interface draft: ================
factory<T> // constructs X and returns it by value factory<T*> // uses operator new, returns a pointer
auto_ptr, please.
Generic algorithms won't 'get' it.
You have generic algorithms that expect to get ownership of a dynamically-allocated pointer?
In this light, it seems better to have a separate template for pointers, so you clients can specify what they want, explicitly:
new_< T* > new_< auto_ptr<T> > new_< special_smartie<T> >
(Seems tricky to deduce T but it might be doable).
boost::pointee<X>::type
Where operator() takes a variable number of arguments, forwarded to the constructor.
Isn't in-place construction the most general case?
It sure is, but not necessarily the most handy. How to tell e.g. std::transform to allocate memory for the transformed elements?
Not sure I really got your point, here.
Just that you might want to support the general case and build the others on top... if possible. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

David Abrahams wrote:
on Tue Jun 19 2007, Tobias Schwinger <tschwinger-AT-isonews2.com> wrote:
David Abrahams wrote:
on Sun Jun 17 2007, Tobias Schwinger <tschwinger-AT-isonews2.com> wrote:
Interface draft: ================
factory<T> // constructs X and returns it by value factory<T*> // uses operator new, returns a pointer auto_ptr, please. Generic algorithms won't 'get' it.
You have generic algorithms that expect to get ownership of a dynamically-allocated pointer?
At least there are generic algorithms that might as well move pointers to dynamic memory: instances.reserve(args.size()); // throws now, if out of memory transform(args.begin(),args.end(),back_inserter(instances), bind( factory<something*>(), 123, _1) ); One could argue that 'instances' should be a boost::ptr_vector - but it isn't needed that badly in cases like this one.
In this light, it seems better to have a separate template for pointers, so you clients can specify what they want, explicitly:
new_< T* > new_< auto_ptr<T> > new_< special_smartie<T> >
(Seems tricky to deduce T but it might be doable).
boost::pointee<X>::type
Oh thanks (I remember the discussion but never noticed it actually became reality :-) )!
Where operator() takes a variable number of arguments, forwarded to the constructor.
Isn't in-place construction the most general case? It sure is, but not necessarily the most handy. How to tell e.g. std::transform to allocate memory for the transformed elements?
Not sure I really got your point, here.
Just that you might want to support the general case and build the others on top... if possible.
That's essentially allocator support, isn't it? I doubt that STL-style allocators are too well-suited for this purpose, however... What's the interface you had in mind? Regards, Tobias

I'd love to have something like this in Boost.Utility! I've run in to situations where it would have been useful many times. Best Regards, Johan Torp -- View this message in context: http://www.nabble.com/boost%3A%3Afactory--tf3937069.html#a11194557 Sent from the Boost - Dev mailing list archive at Nabble.com.

I ran across a similar problem when I implemented my observable_value suggestion (http://lists.boost.org/Archives/boost/2007/06/123263.php) and wanted to write a generic operator<T>= for all operators (+=, /=, %= and so on). The problem with operators of built-in types seems a bit related to those of constructors; you can't treat them as ordinary function pointers. It'd be great if this proposed library could solve this "operator problem" too. IMHO, a solution to the operator problem is not near as important but if there is a general and not much more complicated solution to both, it would be great. Best Regards, Johan Torp -- View this message in context: http://www.nabble.com/boost%3A%3Afactory--tf3937069.html#a11541145 Sent from the Boost - Dev mailing list archive at Nabble.com.

Johan Torp wrote:
I ran across a similar problem when I implemented my observable_value suggestion (http://lists.boost.org/Archives/boost/2007/06/123263.php) and wanted to write a generic operator<T>= for all operators (+=, /=, %= and so on).
The problem with operators of built-in types seems a bit related to those of constructors; you can't treat them as ordinary function pointers.
It'd be great if this proposed library could solve this "operator problem" too. IMHO, a solution to the operator problem is not near as important but if there is a general and not much more complicated solution to both, it would be great.
That would be something like DEFINE_FUNCTION_OBJECT_FOR_EXPRESSION(assign_op, 2, _1 += 2); and it's indeed implementable with C++0x. Regards, Tobias
participants (8)
-
David Abrahams
-
Eric Niebler
-
Glyn Matthews
-
Joel de Guzman
-
Johan Torp
-
Marcus Lindblom
-
Mathias Gaunard
-
Tobias Schwinger