Deterimining interest in: Optional Polymorphic Value object with Small Object optimization

Hi Following the recent interest in clone pointers and Polymorphic value object wrappers, I developed a slightly feature enriched Polymorphic Value object, that implements the small object optimization, and models the Optional Pointee concept. It follows a non-intrusive approach to cloning. The code can be found in the boost vault: *http://tinyurl.com/3a6sq8* Motivation: Dynamic polymorphism is a valuable but underestimated tool to the modern C++ programmer. It for example allows the implementation of type erasure and other techniques for physical decoupling. It is also unavoidable every time dynamic dispatching is needed. Unfortunately solutions based on it may often be slow, because traditional dynamic polymorphism is always paired with dynamic allocation. The proposed tool is targeted to ease the usage of dynamic polymorphism in modern C++ context, by giving value semantics to polymorphic objects, as well as providing a well known optimization technique to avoid dynamic allocation when the involved objects are small. Dynamic polymorphism, value semantics and small object optimization constitute a powerful receipt to solve such problems. As evidence boost::function, among the most valuable tools for type erasure and physical decoupling available in boost, is using all three of them. This tool is meant to be a low level tool, on which powerful abstractions like boost::function could be built easily. Basic Usage Example: #include "optional_poly.hpp" #include <iostream> // class with one virtual method but not virtual destructor // optional_poly will know the derived type, so it will call the correct destructor nevertheless struct B { virtual operator int() {return 0;}}; // lack of virtual destructor is intentional // Derived class, with side effect in destructor to show functionality, and overloaded virtual method to determine which one was called struct D : B { operator int() {return 1;} ~D() { std::cerr<<"Got it\n"; } void swap(D&) {} private: void operator=(D const &); }; // swap reachable via ADL. optional_poly will prefer (by default) this to implement its swap method. Using a trait, you can specify if a swap method or no swap at all should be used for a given type void swap(D& a,D& b) { a.swap(b); } int main() { // optional_poly constructor and operator= require that the static type match the dynamic one. // The following commented code is invalid, and will assert at runtime // const B& d=D(); // boost::optional_poly<B> z=d; // asserts, because optional_poly should be constructed with the concrete derived type // this is the correct way to initialize optional_poly. D must be derived from B (static assertion otherwise). boost::optional_poly<B> z=D(); std::cerr<<*z<<"\n"; // this prints 1 boost::optional_poly<B> s; // uninitialized (empty) optional_poly for interface B s.swap(z); // now s has a D, while z is empty std::cerr<<*s<<"\n"; // prints 1 return 0; } A bit more complex example: #include "optional_poly.hpp" #include <boost/none.hpp> #include <iostream> // we will show how simple callable objects can be returned easily and efficiently from a function (i.e. we implement a really small subset of boost::function) struct Callable { virtual void operator()() const=0; }; // inheritance is used here. This wrapper can host function pointers or functors seamlessly, exposing to the outside the Callable interface template<class T> struct MakeCallable: Callable { MakeCallable(const T& t) : val(t) {} T val; void operator()() const { val(); } }; void my_fun() { std::cout<<"got 1\n"; } struct MyFunc { void operator()() const { std::cout<<"got 2\n"; } }; // the function returning different Callable objects depending on the value of the parameter boost::optional_poly<Callable> foo(int i) { switch(i) { case 1: return MakeCallable<void (*)()>(my_fun); case 2: return MakeCallable<MyFunc>(MyFunc()); } return boost::none; } // main shows how foo() is invoked, and its result is used int main() { boost::optional_poly<Callable> c; for(int i=0;i<3; ++i) { c=foo(i); if(c) { std::cout<<"Going to call c for "<<i<<" ... ";(*c)(); } else { std::cout<<"empty c for "<<i<<"\n"; } } return 0; } Output: empty c for 0 Going to call c for 1 ... got 1 Going to call c for 2 ... got 2 Wasn't this easy? And this small example did not dynamically allocate any memory, because the Callable objects are all smaller than the small object threshold (default value is 128, can be overridden specifying a second template parameter to optional_poly, e.g. optional_poly<Callable,0> will always allocate from the heap). Sounds interesting for being submitted to boost? Corrado -- __________________________________________________________________________ dott. Corrado Zoccolo mailto: zoccolo@di.unipi.it PhD - Department of Computer Science - University of Pisa, Italy --------------------------------------------------------------------------

So, is this more a boost::any with SBO or a boost::optional that can store polymorphic types if necessary? It seems to me like it is the latter. That sounds useful, but right now I'd need the former. Sebastian Redl

http://opensource.adobe.com/classadobe_1_1poly.html On 10/20/07, Sebastian Redl <sebastian.redl@getdesigned.at> wrote:
So, is this more a boost::any with SBO or a boost::optional that can store polymorphic types if necessary?
It seems to me like it is the latter. That sounds useful, but right now I'd need the former.
Sebastian Redl _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Hi Simon On 10/20/07, Simon Francis <thejello@gmail.com> wrote:
http://opensource.adobe.com/classadobe_1_1poly.html
I already knew adobe poly, when I started writing optional_poly. The aim
is similar, but the approach is completely different. With Adobe poly, you have to design the interfaces, and write "concept maps" to specifically to work with it. Example, from Adobe poly test: struct poly_measurable_interface : adobe::poly_copyable_interface { virtual double size() const = 0; virtual ~poly_measurable_interface() { } }; /*************************************************************************************************/ // This class template implements the abstract measurable interface in terms of a type T that // Models the MeasurableConcept template <typename T> struct poly_measurable_instance : adobe::optimized_storage_type<T, poly_measurable_interface>::type { ADOBE_CLASS_REQUIRE(T, , MeasurableConcept); poly_measurable_instance(const T& x) : adobe::optimized_storage_type<T, poly_measurable_interface>::type(x) {} poly_measurable_instance(poly_measurable_instance& x, adobe::move_ctor m) : adobe::optimized_storage_type<T, poly_measurable_interface>::type(x, m) {} double size() const { return MeasurableConcept<T>::size(this->get()); } }; /*************************************************************************************************/ // Another boilerplate class, measurable serves as a template parameter to the poly<> machinery // tying together the interface and implementation above. struct measurable : adobe::poly_base<poly_measurable_interface, poly_measurable_instance> { // No delegating constructors (yet), so we call base constructor manually template <typename T> explicit measurable(const T& s) : adobe::poly_base<poly_measurable_interface, poly_measurable_instance>(s) { } measurable(measurable& x, adobe::move_ctor m) : adobe::poly_base<poly_measurable_interface, poly_measurable_instance>(x, m) {} // No forwarding in C++, so we do it manually double size() const { return interface_ref().size(); } }; typedef adobe::poly<measurable> poly_measurable; Thanks to all this boilerplate code, you can use the usual dot notation to access the members of the class. My approach is different. You don't have to change the interfaces to use optional_poly (so it is non intrusive with existing hierarchies), and you don't need all this boilerplate code, but you have to use the -> operator to access members of the class. Moreover, optional_poly, as the name suggests, is nullable. The previous example with optional_poly will simply become: struct poly_measurable_interface { virtual double size() const = 0; virtual ~poly_measurable_interface() { } }; typedef optional_poly< poly_measurable_interface > optional_poly_measurable; Corrado -- __________________________________________________________________________ dott. Corrado Zoccolo mailto:zoccolo@di.unipi.it PhD - Department of Computer Science - University of Pisa, Italy --------------------------------------------------------------------------

A new release of boost overload is out. You can find it under overload-mrcec in boost vault. Link: http://tinyurl.com/2w4wob I remind you that boost overload is a thin wrapper around a set of boost::function objects, and behaves as an overloaded boost::function. You can read more about boost overload here: http://docs.google.com/Doc?id=dhd386mp_16gxsfxn The documentation was kindly written down by Dean Michael Berris. Moreover you can give a look at a tutorial updated to the latest release of the library here: http://docs.google.com/Doc?id=dfxvjncs_1x6456m what's new in version 0.3.0 (overload-0.3.0.zip) ================================================ - added partial support for MSVC 7.1, all work but signature deduction of multi-signature function objects, you have to use the signature based syntax in order to set multi-signature function objects as callable targets; - you can set a free function overload or a member function overload as callable target through the signature based syntax; for more info give a look to the tuturial; the same applies to template free functions and template member functions; - added two new helper methods - the empty_all method that tell us if all callable targets are empty; - the clear_all method that clears all the callable targets; - in the folder libs/overload/example you can find all the examples presented in the tutorial; - fixed some minor issue. Compiler support table ====================== compiler OS test ------------------------------------------- gcc 4.1.2 under Linux pass intel 9.1 under Linux pass mingw 3.4.2 under Windows pass mingw 3.2.3 under Windows fail MS VC++ 8.0 under Windows pass MS VC++ 7.1 under Windows partial Boost community suggestions and critiques about interface, implementation and documentation are welcome. Above all I'd appreciate anyone pointing out bugs, compatibility issues, and library use cases. Regards, Marco Cecchetti -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/

On 10/31/07, Marco <mrcekets@gmail.com> wrote:
A new release of boost overload is out. You can find it under overload-mrcec in boost vault. Link: http://tinyurl.com/2w4wob
Compiles and runs for me: Mandriva with gcc 4.2.2 Impressive! almost a world apart from it's humble origins ;-) Marco

Marco Costalba wrote:
On 10/31/07, Marco <mrcekets@gmail.com> wrote:
A new release of boost overload is out. You can find it under overload-mrcec in boost vault. Link: http://tinyurl.com/2w4wob
Compiles and runs for me: Mandriva with gcc 4.2.2
Impressive! almost a world apart from it's humble origins ;-)
Very good! Keep up the good work! Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

On 11/1/07, Joel de Guzman <joel@boost-consulting.com> wrote:
Impressive! almost a world apart from it's humble origins ;-)
Very good! Keep up the good work!
To me it would seem that the good work is almost finished! Marco, why don't you apply for a review?

On Thu, 01 Nov 2007 09:13:22 +0100, Marco Costalba <mcostalba@gmail.com> wrote:
On 11/1/07, Joel de Guzman <joel@boost-consulting.com> wrote:
Impressive! almost a world apart from it's humble origins ;-)
Very good! Keep up the good work!
To me it would seem that the good work is almost finished!
Marco, why don't you apply for a review? _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Indeed it still needs polishing, boostification and above all more exhaustive and rigorous testing. I should read Boost Test docs and use it. At present my target is to get the implementation uploaded in the boost svn sandbox in order to make easier the collaboration between boost developers interested in the library. I sent a request to boost moderators to get read/write access, to the sandbox, and I'm waiting for a reply. PS: are you still in China ? Send me a photo! :-) Have a great day ! Ciao Marco -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/

On Thu, Nov 01, 2007 at 08:41:56AM +0800, Joel de Guzman wrote:
Marco Costalba wrote:
On 10/31/07, Marco <mrcekets@gmail.com> wrote:
A new release of boost overload is out. You can find it under overload-mrcec in boost vault. Link: http://tinyurl.com/2w4wob
Compiles and runs for me: Mandriva with gcc 4.2.2
Impressive! almost a world apart from it's humble origins ;-)
I checked it with gcc 3.3, 3.4 4.1, 4.2, 4.3 and it works indeed great and all tests are successful with one exception: There are warnings and even internal compiler errors with gcc 3.3! $ g++-3.3 --version g++-3.3 (GCC) 3.3.6 (Debian 1:3.3.6-15) I attached a patch which just adds a few comments which you should check. It's only very trivial stuff. Most internal compiler errors result from static asserts which I excluded for g++ 3.3. But at least one test leads to it as well outside asserts. PS: Please do not create ZIP files from your DOS based system. All files (even source files!) are marked as executable which is obviously wrong. Jens

On Thu, 01 Nov 2007 09:59:28 +0100, Jens Seidel <jensseidel@users.sf.net> wrote:
I checked it with gcc 3.3, 3.4 4.1, 4.2, 4.3 and it works indeed great and all tests are successful with one exception:
There are warnings and even internal compiler errors with gcc 3.3!
$ g++-3.3 --version g++-3.3 (GCC) 3.3.6 (Debian 1:3.3.6-15)
I attached a patch which just adds a few comments which you should check. It's only very trivial stuff. Most internal compiler errors result from static asserts which I excluded for g++ 3.3. But at least one test leads to it as well outside asserts.
Thanks for your extensive testing ! :-) Indeed I didn't perform any test with gcc 3.3 but from what you pointed out it seems that doesn't support the Mesonides' trick and this cuts away signature deduction of any function object. Could you suggest me some paper about compiler bugs, unsupported features and possible workarounds.
PS: Please do not create ZIP files from your DOS based system. All files (even source files!) are marked as executable which is obviously wrong.
Jens
Do you mean the zip files I upload into the vault ? I always create them under linux, so this sounds really odd to me. However I can create .tar.gz archive if this can be helpful. Let me know. Marco -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/

On Thu, Nov 01, 2007 at 02:51:55PM +0100, Marco wrote:
On Thu, 01 Nov 2007 09:59:28 +0100, Jens Seidel <jensseidel@users.sf.net> wrote:
I checked it with gcc 3.3, 3.4 4.1, 4.2, 4.3 and it works indeed great and all tests are successful with one exception:
Thanks for your extensive testing ! :-) Indeed I didn't perform any test with gcc 3.3 but from what you pointed out it seems that doesn't support the Mesonides' trick and this cuts away signature deduction of any function object.
Right, maybe you should not even try to support gcc 3.3 if it causes such problems. Maybe you find nevertheless a clean workaround, I don't know. If you need more information such as a callstack just ask ...
Could you suggest me some paper about compiler bugs, unsupported features and possible workarounds.
No sorry. I just dicovered it during my tests. For bugs you could of course check the bug database of GNU. I'm not sure but I think it's useless to report the bug in gcc 3.3 and hope it gets fixed (it's too old!?) but maybe you can still just report it to get a bug number for references.
PS: Please do not create ZIP files from your DOS based system. All files (even source files!) are marked as executable which is obviously wrong.
Jens
Do you mean the zip files I upload into the vault ?
I referred to the ZIP file you referenced in this thread (a tinyurl one). I extracted it via a simple unzip, I cannot image that I did something wrong. Could it be that ZIP archives do not support file permissions at all? I don't know ...
I always create them under linux, so this sounds really odd to me. However I can create .tar.gz archive if this can be helpful. Let me know.
The best solution is probably to get it integrated into sandbox. I have no trouble with wrong file permissions for a testing version but if all archives for the next few years will be broken I suggest to improve the situation. Jens

Sorry for top posting, but... The Overloads library is now available in the Boost Subversion Sandbox -- I've gotten permission from Marco Ceccheti to upload the implementation, which can now be collaboratively developed through the Boost Subversion Sandbox space. You should be able to access the overload implementation at http://svn.boost.org/svn/boost/sandbox/overload/trunk -- this version is derived from Marco Ceccheti's implementation, with certain changes for complying with some Boost rules about filenames (length, etc.) and directory layout. Documentation using Quickbook will be under way, starting with the documentation I've written http://tinyurl.com/2e85xc and the Boost.Overload tutorial http://tinyurl.com/yqbqw9 by Marco Ceccheti. Now to address some of the issues below (to keep this post coherent): On 11/1/07, Jens Seidel <jensseidel@users.sf.net> wrote:
I always create them under linux, so this sounds really odd to me. However I can create .tar.gz archive if this can be helpful. Let me know.
The best solution is probably to get it integrated into sandbox. I have no trouble with wrong file permissions for a testing version but if all archives for the next few years will be broken I suggest to improve the situation.
The above announcement should be very a welcome change for you. I hope this helps! -- Dean Michael C. Berris Software Engineer, Friendster, Inc. [http://cplusplus-soup.blogspot.com/] [mikhailberis@gmail.com] [+63 928 7291459] [+1 408 4049523]

Hi Michael, thanks a lot for uploading the library into the sandbox and for having modified the folders layout according to the boost guidelines. At present I've some mail connection issue. But I hope to get them solved soon. Anyone interested in boost overload can start checking out the library ! .. and have fun ! :-) Kind Regards, Marco On Thu, 01 Nov 2007 16:48:34 +0100, Dean Michael Berris <mikhailberis@gmail.com> wrote:
Sorry for top posting, but...
The Overloads library is now available in the Boost Subversion Sandbox -- I've gotten permission from Marco Ceccheti to upload the implementation, which can now be collaboratively developed through the Boost Subversion Sandbox space.
You should be able to access the overload implementation at http://svn.boost.org/svn/boost/sandbox/overload/trunk -- this version is derived from Marco Ceccheti's implementation, with certain changes for complying with some Boost rules about filenames (length, etc.) and directory layout.
Documentation using Quickbook will be under way, starting with the documentation I've written http://tinyurl.com/2e85xc and the Boost.Overload tutorial http://tinyurl.com/yqbqw9 by Marco Ceccheti.
Now to address some of the issues below (to keep this post coherent):
On 11/1/07, Jens Seidel <jensseidel@users.sf.net> wrote:
I always create them under linux, so this sounds really odd to me. However I can create .tar.gz archive if this can be helpful. Let me know.
The best solution is probably to get it integrated into sandbox. I have no trouble with wrong file permissions for a testing version but if all archives for the next few years will be broken I suggest to improve the situation.
The above announcement should be very a welcome change for you. I hope this helps!
-- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/

On 11/1/07, Marco <mrcekets@gmail.com> wrote:
Hi Michael,
thanks a lot for uploading the library into the sandbox and for having modified the folders layout according to the boost guidelines. At present I've some mail connection issue. But I hope to get them solved soon.
My pleasure. I hope you get the mail connection issues resolved soon.
Anyone interested in boost overload can start checking out the library ! .. and have fun ! :-)
And in case you have questions/suggestions/comments, please feel free to ask them on the mailing list! -- Dean Michael C. Berris Software Engineer, Friendster, Inc. [http://cplusplus-soup.blogspot.com/] [mikhailberis@gmail.com] [+63 928 7291459] [+1 408 4049523]

On Thu, Nov 01, 2007 at 08:48:34AM -0700, Dean Michael Berris wrote:
The Overloads library is now available in the Boost Subversion Sandbox
Great!
You should be able to access the overload implementation at http://svn.boost.org/svn/boost/sandbox/overload/trunk -- this version is derived from Marco Ceccheti's implementation, with certain changes for complying with some Boost rules about filenames (length, etc.) and directory layout.
Are you sure the directory layout is OK? I would not expect to see trunk in http://svn.boost.org/svn/boost/sandbox/overload but the content of it. Branches belong to http://svn.boost.org/svn/boost/sandbox-branches so http://svn.boost.org/svn/boost/sandbox/<project> should always contain the trunk version without need to create an additional directory called "trunk". At least the logging library doesn't use "trunk". Let me summarise: Instead of http://svn.boost.org/svn/boost/sandbox/overload/trunk/boost I would expect http://svn.boost.org/svn/boost/sandbox/overload/boost. If I'm wrong other projects should maybe restructered for consistency.
The above announcement should be very a welcome change for you. I hope this helps!
It does, thanks! Jens

Hi Jens, On 11/1/07, Jens Seidel <jensseidel@users.sf.net> wrote:
On Thu, Nov 01, 2007 at 08:48:34AM -0700, Dean Michael Berris wrote:
You should be able to access the overload implementation at http://svn.boost.org/svn/boost/sandbox/overload/trunk -- this version is derived from Marco Ceccheti's implementation, with certain changes for complying with some Boost rules about filenames (length, etc.) and directory layout.
Are you sure the directory layout is OK? I would not expect to see trunk in http://svn.boost.org/svn/boost/sandbox/overload but the content of it. Branches belong to http://svn.boost.org/svn/boost/sandbox-branches so http://svn.boost.org/svn/boost/sandbox/<project> should always contain the trunk version without need to create an additional directory called "trunk". At least the logging library doesn't use "trunk".
I'm talking about the directory layout as far as the root of the project is concerned. This follows the convention of Boost libraries that can easily be 'untarred into the Boost Root directory, and play nice with the other boost libraries'. As far as using trunk is concerned, I haven't seen any rules as to how a self-contained development environment can be maintained for the whole sandbox, which all the other libraries will have to follow. As far as I can tell (or at least as far as subversion goes), a branch is basically a copy of a source tree in another directory. There are no hard-coded conventions, and I don't see one for the sandbox.
Let me summarise: Instead of http://svn.boost.org/svn/boost/sandbox/overload/trunk/boost I would expect http://svn.boost.org/svn/boost/sandbox/overload/boost.
If I'm wrong other projects should maybe restructered for consistency.
I don't think either of us are wrong or right. I think it's a matter of preference as far as the sandbox is concerned -- and on a per-project basis, I think it should be alright to have different approaches. After all, all the stuff there isn't official by an Boost standard IIRC.
The above announcement should be very a welcome change for you. I hope this helps!
It does, thanks!
You're welcome. Have fun! -- Dean Michael C. Berris Software Engineer, Friendster, Inc. [http://cplusplus-soup.blogspot.com/] [mikhailberis@gmail.com] [+63 928 7291459] [+1 408 4049523]

On Thu, 01 Nov 2007 01:41:56 +0100, Joel de Guzman <joel@boost-consulting.com> wrote:
Marco Costalba wrote:
On 10/31/07, Marco <mrcekets@gmail.com> wrote:
A new release of boost overload is out. You can find it under overload-mrcec in boost vault. Link: http://tinyurl.com/2w4wob
Compiles and runs for me: Mandriva with gcc 4.2.2
Impressive! almost a world apart from it's humble origins ;-)
Very good! Keep up the good work!
Thanks for your initial implementation :-) I hope that boost overload can be useful for other projects, too. Marco -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/

Marco wrote:
A new release of boost overload is out.
[...]
You can read more about boost overload here: http://docs.google.com/Doc?id=dhd386mp_16gxsfxn The documentation was kindly written down by Dean Michael Berris.
Looks interesting. Just one naive question... If a overload variable can be set any function, why bother giving it a signature when declaring it? Why not just: overload<> f; // or simply boost::overload f; f.set(&int_sum); // here automatic signature f.set(&float_inc); // deduction occurs f.set(&any_function);

On 11/2/07, gchen <chengang31@gmail.com> wrote:
Marco wrote:
A new release of boost overload is out.
[...]
You can read more about boost overload here: http://docs.google.com/Doc?id=dhd386mp_16gxsfxn The documentation was kindly written down by Dean Michael Berris.
Looks interesting. Just one naive question...
If a overload variable can be set any function, why bother giving it a signature when declaring it?
That is because you need to know what signatures the overload instance will support. In C++, you have no way of modifying a type at runtime -- and that's why what you propose is nearly impossible if not impractical to implement. This is the same reason why Boost.Function needs this information as well, to know what signature it will expose and support wrapping. -- Dean Michael C. Berris Software Engineer, Friendster, Inc. [http://cplusplus-soup.blogspot.com/] [mikhailberis@gmail.com] [+63 928 7291459] [+1 408 4049523]

On 11/2/07, Dean Michael Berris <mikhailberis@gmail.com> wrote:
On 11/2/07, gchen <chengang31@gmail.com> wrote:
That is because you need to know what signatures the overload instance will support. In C++, you have no way of modifying a type at runtime -- and that's why what you propose is nearly impossible if not impractical to implement.
I would say it's impossible in C++ ;-) I stumbled on this during my little object factory development. The reason it is impossible is that templates do not change the type of already defined variables. In your example: overload<> f; // after compiler processes the above statement the type of 'f' has been exactly //defined, 'f' is no more a template after compilation of this line! so type of 'f' // cannot be changed again but... f.set(&int_sum); // ...it should be because the above line would change the type of 'f' as soon as // compiler process the above statement. So the reason the above is impossible is that: - After compilation of a template variable definition, the variable assumes a fixed, complete type. - In C++ type of a variable cannot be changed once the variable has been defined. Hope this is clear. Marco

Marco Costalba wrote:
On 11/2/07, Dean Michael Berris <mikhailberis@gmail.com> wrote:
On 11/2/07, gchen <chengang31@gmail.com> wrote:
That is because you need to know what signatures the overload instance will support. In C++, you have no way of modifying a type at runtime -- and that's why what you propose is nearly impossible if not impractical to implement.
I would say it's impossible in C++ ;-)
Actually it is possible in c++. You push the overload resolution at runtime. It will never be as efficient though. With this implementation, you use the C++ compiler to select the correct overload for you. Very fast. Without a constrained list of signatures, the compiler cannot be used to do the selection. You are on your own. You have to perform the overload resolution by mimicking the way overload resolution takes place in C++ in your code at runtime. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

On 11/3/07, Joel de Guzman <joel@boost-consulting.com> wrote:
I would say it's impossible in C++ ;-)
Actually it is possible in c++. You push the overload resolution at runtime. It will never be as efficient though. With this implementation, you use the C++ compiler to select the correct overload for you. Very fast. Without a constrained list of signatures, the compiler cannot be used to do the selection. You are on your own. You have to perform the overload resolution by mimicking the way overload resolution takes place in C++ in your code at runtime.
The problem I see is not the overload resolution that is some way you _could_ resolve at runtime using dynamic polymorphism, i.e deriving all the functions objects wrappers from a base class and store a new pointer to base class for each function registered with set(). The problem is the calling of the registered functions with the correct number and types of arguments. For that you cannot rely on a common base class. In the fist version of my little object factory I use an involved matching algorithm to overcome this. I tried, given the argument list to use at calling time, to find a stored function with the _same_ argument types (note not compatible, because implicit conversions does not work in this case). The matching was based on dyamic_cast (one could think also of typeid). It works but the result is suboptimal: no implicit conversions, no compile time errors for unmatching arguments, still difficult to handle all the const-volatile-reference combinations. The last version, the one now in Vault, uses pre-registartion of signatures at compile time: it's far more easier and efficient and powerful (implicit conversions do work). Marco

On Fri, 02 Nov 2007 09:47:14 +0100, gchen <chengang31@gmail.com> wrote:
Marco wrote:
A new release of boost overload is out.
[...]
You can read more about boost overload here: http://docs.google.com/Doc?id=dhd386mp_16gxsfxn The documentation was kindly written down by Dean Michael Berris.
Looks interesting. Just one naive question...
If a overload variable can be set any function, why bother giving it a signature when declaring it? Why not just:
overload<> f; // or simply boost::overload f;
f.set(&int_sum); // here automatic signature f.set(&float_inc); // deduction occurs
f.set(&any_function);
Well the reason is that we can deduce the signature but then we have to store the passed argument in a function pointer of the correct type ( == with the correct signature ), otherwise we can't use it to forwarding a call to the function it points to. The issue is that the deduction occurs at run time, while we need to know the correct type at compile time. Marco -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/

On Oct 20, 2007 1:15 PM, Corrado Zoccolo <czoccolo@gmail.com> wrote:
Hi Simon
On 10/20/07, Simon Francis <thejello@gmail.com> wrote:
http://opensource.adobe.com/classadobe_1_1poly.html
I already knew adobe poly, when I started writing optional_poly. The aim
is similar, but the approach is completely different. With Adobe poly, you have to design the interfaces, and write "concept maps" to specifically to work with it.
Example, from Adobe poly test:
struct poly_measurable_interface : adobe::poly_copyable_interface { virtual double size() const = 0;
virtual ~poly_measurable_interface() { } };
/*************************************************************************************************/ // This class template implements the abstract measurable interface in terms of a type T that // Models the MeasurableConcept
template <typename T> struct poly_measurable_instance : adobe::optimized_storage_type<T, poly_measurable_interface>::type { ADOBE_CLASS_REQUIRE(T, , MeasurableConcept);
poly_measurable_instance(const T& x) : adobe::optimized_storage_type<T, poly_measurable_interface>::type(x) {}
poly_measurable_instance(poly_measurable_instance& x, adobe::move_ctor m) : adobe::optimized_storage_type<T, poly_measurable_interface>::type(x, m) {}
double size() const { return MeasurableConcept<T>::size(this->get()); } };
/*************************************************************************************************/ // Another boilerplate class, measurable serves as a template parameter to the poly<> machinery // tying together the interface and implementation above.
struct measurable : adobe::poly_base<poly_measurable_interface, poly_measurable_instance> { // No delegating constructors (yet), so we call base constructor manually template <typename T> explicit measurable(const T& s) : adobe::poly_base<poly_measurable_interface, poly_measurable_instance>(s) { }
measurable(measurable& x, adobe::move_ctor m) : adobe::poly_base<poly_measurable_interface, poly_measurable_instance>(x, m) {}
// No forwarding in C++, so we do it manually double size() const { return interface_ref().size(); } };
typedef adobe::poly<measurable> poly_measurable;
Thanks to all this boilerplate code, you can use the usual dot notation to access the members of the class.
My approach is different. You don't have to change the interfaces to use optional_poly (so it is non intrusive with existing hierarchies), and you don't need all this boilerplate code, but you have to use the -> operator to access members of the class.
[snip] -------------- There have been a few posts on the boost lists recently mentioning the adobe::poly library. Since the poly documentation is still somewhat incomplete, except for a few research-orineted papers, I thought I'd give a bit more detail here, to help clarify the differences between poly<> and possibly similar libraries. You correctly note that the adobe::poly library requires more machinery to be provided by certain stakeholers. It does not, however, intrude into existing concrete classes. To better understand where the adobe::poly library lives in the design continuum, I'll consider a possible manner in which a piece of code may over its lifetime. I'll start with a (toy example of a) class that automatically sizes and positions widgets from a particular GUI library inside of a dialog. In this scenario, users of the layout engine first "append" widgets to the layout collection. Once all the widgets have been appended, the user can ask the engine to "solve" the layout. In order to solve the layout, the engine will call a measure function on each widget to obtain its desired extents and other layout constraints. When the layout is solved, the engine informs the widgets of their final location by invoking the place(Widget, extents_t) member function: // // Code evolution: stage 1-- //layout engine operating on aspecific concrete type class Widget {/*...*/}; // API-specific widget class class extents_t {/*...*/}; // encapsulates screen object size and location struct layout_engine { void append(Widget placeable) { placeables_m.push_back(placeable); } void solve() { extents_m.resize(placeables_m.size()); for(int i = 0; i != placeables_m.size(); ++i) measure(placeables_m[i], extents_m[i]); // ommitted: code to solve layout constraints // and update place_data_m (ommitted) for(int i = 0; i != placeables_m.size(); ++i) place(placeables_m[i], place_data_m[i]); } vector<extents_t> extents_m; vector<Widget> placeables_m; }; Version #1 of the engine above is designed to work on a single specific Widget type. Later in life, this code is to be ported to other platforms. One approach to generalization is to templatize the layout engine on the widget type. The code for the layout engine doesn't need to change. // // Code evolution: stage 2 --lifting the engine // (at compile time) using templates // template <class T> struct layout_engine { void append(T placeable) { placeables_m.push_back(placeable); } void solve() { extents_m.resize(placeables_m.size()); for(int i = 0; i != placeables_m.size(); ++i) measure(placeables_m[i], extents_m[i]); // ommitted: code to solve layout constraints // and update place_data_m (ommitted) for(int i = 0; i != placeables_m.size(); ++i) place(placeables_m[i], place_data_m[i]); } vector<extents_t> extents_m; vector<T> placeables_m; }; Version #2 of the code (above) assumes that measure and place operations with the right signatures are implemented for the T widget type. To improve usability of our class template, we use the boost::concept_check library to improve error messages in case the required measure and place operations are not present (not shown here). In the test code for adobe::poly that you cited above, you can see some of this machinery (ADOBE_CLASS_REQUIRE). We go even further simulating the C++ '0x concept_map feature through the use of operations qualified by MeasurableConcept. But this is not really poly<>-specific so I won't say more about it now. For the next stage of our code's evolution, we wish be able to use the layout engine in contexts where the widget type is not known until runtime. Since we don't wish to intrude on our concrete widget types to make them inherit from a base class, the usual object-oriented abstract base class approach doesn't appeal. Such an approach might not even be possible, given that we may not control the source code for the widget classes. One principle applied in the design of the poly<> library was that the ability for an object to behave polymorphically is not one that should be introduced/paid for at design-time. Instead, we support a pay-as-you-go plan at the point of polymorphic use. The adobe::poly library is a toolkit designed to facilitate the task of providing non-intrusive value-based wrappers that allow concrete classes to be used in a runtime polymorphic manner, without change of interface. We could retain the previous version of the layout_engine unchanged, instantiating it on the poly_placeable runtime polymorphic wrapper when we want runtime polymorphic behavior, and we could instantiate the layout engine "library" on a concrete type in applications where the widget type is known at compile time. For the runtime-polymorphic wrapper case this would simply look like: // Code evolution: stage 3 -- instantiating the layout_engine class on // the runtime polymorphic wrapper type poly_placeable layout_engine<poly_placeable> e; As an alternate use case (e.g. for dynamic libraries), we sometimes emphasize the runtime polymorphic usage by promoting/de-templatizing the layout_engine class template into a plain (non-templated) class: struct layout_engine { void append(poly_placeable placeable); void solve(); vector<extents_t> extents_m; vector<poly_placeable> placeables_m; }; The current version of the poly library assumes two different kinds of clients. The first kind of client (the wrapper author) is the provider of a poly "wrapper", such as the poly_measurable wrapper above. This client uses the poly library to reduce the burden of producing a particular non-intrusive polymorphic value type. Such clients must provide: an abstract base class specifying the required/available operations, (this is the role of poly_measurable_interface in the poly_test code), a class template that implementing the abstract interface in terms of concrete types that provide offer the appropriate signature (this is the role of poly_measurable_instance in the poly_test example), and a small glue class that holds the previous two artifacts together (measureable in the adobe_test example). Once those three artifacts have been written, the poly<> wrapper can be instantiated: typedef adobe::poly<measurable> poly_measurable; // in the poly_test example Poly offers a number of other features (small object optimization, move semantics using the NRVO-based adobe::move library, etc.) but I won't discuss those further. At this point the responsibilities of the first kind of poly client, the wrapper author, are complete. The second kind of client is the end user of classes such as poly_placeable. In the evolving code example above, we can look briefly at how the code that calls the layout engine evolves. The stage 1 calling sequence might look like: void place(widget, extents_t); exents_t measure(widget, extents_t); //... layout_engine e; // #1 void layout_dialog() { Widget widget1, widget2; //append some widgets: e.append(widget1); //#2 e.append(widgetn); //#3 //... e.solve(); } At stage 2, the only line that changes is #1: layout_engine<Widget> e; //#1' At stage 3, we need to change //#1 once more to layout_engine<poly_placeable> e; //#1'' In the conceptC++ version of poly, or in a version in which poly_constructors were non-explicit, no further changes would be required. In the current C++ '03 version, poly<> has an explicit constructor, so we also change lines #2 and #3 to: e.append(poly_placeable(widget1)); //#2'' e.append(poly_placeable(widgetn)); //#3'' I haven't touched on other adobe::poly features such as the assignability across different poly<> types, dynamic dispatch and dynamic_cast that poly can provide, but I've probably already said more than anyone wanted to hear about it in this thread. More info can be found at the following locations: http://opensource.adobe.com/ For the adobe source library (including poly) http://www.emarcus.org/papers/MPOOL2007-marcus.pdf http://www.emarcus.org/papers/MPOOL2007-slides-marcus.pdf # Runtime Polymorphic Generic Programming--Mixing Objects and Concepts in ConceptC++ Mat Marcus, Adobe Systems, Inc., Jaakko Järvi, Texas A&M University, Sean Parent, Adobe Systems, Inc. From: The 6th International Workshop on Multiparadigm Programming with Object-Oriented Languages at the ECOOP 2007. and a little bit here: http://www.speakeasy.org/~mmarcus/papers/gpce2007f-authors-version.pdf # Library Composition and Adaptation using C++ Concepts Jaakko Järvi, Texas A&M University, Mat Marcus, Adobe Systems, Inc., Jacob N. Smith, Texas A&M University. From: Proceedings of the 6th international conference on Generative programming and component engineering, 2007. Copyright ACM, 2007. This is the author's version of the work. It is posted here by permission of ACM for your personal use. Not for redistribution. The definitive version was published in the Proceedings of the 6th International Conference on Generative Programming and Component Engineering (Salzburg, Austria, October 01 - 03, 2007). GPCE '07 http://doi.acm.org/10.1145/1289971.1289984 - Mat

On 11/2/07, Mat Marcus <mat-lists@emarcus.org> wrote:
My approach is different. You don't have to change the interfaces to use optional_poly (so it is non intrusive with existing hierarchies), and you don't need all this boilerplate code, but you have to use the -> operator to access members of the class.
[snip]
You correctly note that the adobe::poly library requires more machinery to be provided by certain stakeholers. It does not, however, intrude into existing concrete classes.
[snip] Ok, we are talking of two different things: intrusiveness w.r.t. existing hierarchies vs. intrusiveness w.r.t. existing concrete classes. Your example shows that adobe::poly<> is not intrusive w.r.t. existing concrete classes, because it simulates concept maps with the boilerplate code, but you are starting from a class that is not polymorphic (I would do a similar think in those cases, look at my Callable example; the only difference is that the boilerplate code seems to me more simple and natural, because we create a hierarchy of classes, as we would usually do in OOP). I'm concerned, though, of the case in which you already have a hierarchy of polymorphic classes, and want to take advantage of value semantics, and other possible optimizations e.g. small object. If you look at my example on how to rewrite boost::any to have the small object optimization using optional_poly, you will see how an existing hierarchy: class placeholder { public: // structors virtual ~placeholder() { } public: // queries virtual const std::type_info & type() const = 0; }; template<typename ValueType> class holder : public placeholder { public: // structors holder(const ValueType & value) : held(value) { } public: // queries virtual const std::type_info & type() const { return typeid(ValueType); } public: // representation ValueType held; }; is completely reused without changes (I only removed an unused method for clarity of the example). I think this is out of adobe::poly scope, or at least it is never covered in the examples, so I cannot figure out how this would be done in practice. Corrado -- __________________________________________________________________________ dott. Corrado Zoccolo mailto:zoccolo@di.unipi.it PhD - Department of Computer Science - University of Pisa, Italy --------------------------------------------------------------------------

On 10/20/07, Sebastian Redl <sebastian.redl@getdesigned.at> wrote:
So, is this more a boost::any with SBO or a boost::optional that can store polymorphic types if necessary?
I haven't looked at boost::any implementation yet, but I guess it is based on the same recipe as boost::function, so I think that what you need can be implemented easily with optional_poly as a basic tool. It seems to me like it is the latter. That sounds useful, but right now
I'd need the former.
I will work on some sample code to show how it can be obtained, and come back. Corrado Sebastian Redl
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- __________________________________________________________________________ dott. Corrado Zoccolo mailto:zoccolo@di.unipi.it PhD - Department of Computer Science - University of Pisa, Italy --------------------------------------------------------------------------

On 10/20/07, Corrado Zoccolo <czoccolo@gmail.com> wrote:
On 10/20/07, Sebastian Redl <sebastian.redl@getdesigned.at> wrote:
So, is this more a boost::any with SBO or a boost::optional that can store polymorphic types if necessary?
I haven't looked at boost::any implementation yet, but I guess it is based on the same recipe as boost::function, so I think that what you need can be implemented easily with optional_poly as a basic tool.
It seems to me like it is the latter. That sounds useful, but right now
I'd need the former.
I will work on some sample code to show how it can be obtained, and come back.
It was actually pretty easy. boost::any used plain dynamic polymorphism through a pointer, so it was only matter of changing this pointer with an optional_poly, and remove some of the ad-hoc code for cloning (achieved automatically with optional_poly). This gives you a boost::any with small object optimization, and shows the potential usefulness of optional_poly as a basic tool to implement higher abstractions with low penalties. I posted this example, as well as the other big example in the vault (* http://tinyurl.com/2rfaah*). Corrado
Sebastian Redl
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- __________________________________________________________________________
dott. Corrado Zoccolo mailto:zoccolo@di.unipi.it PhD - Department of Computer Science - University of Pisa, Italy --------------------------------------------------------------------------
-- __________________________________________________________________________ dott. Corrado Zoccolo mailto:zoccolo@di.unipi.it PhD - Department of Computer Science - University of Pisa, Italy -------------------------------------------------------------------------- The self-confidence of a warrior is not the self-confidence of the average man. The average man seeks certainty in the eyes of the onlooker and calls that self-confidence. The warrior seeks impeccability in his own eyes and calls that humbleness. Tales of Power - C. Castaneda

Corrado Zoccolo wrote:
Sounds interesting for being submitted to boost?
Absolutely impressive. I hope it will be a part of boost. I think your hand-made vtable way is much better than adobe's way. BTW, why not `poly<T>`. `optional_` seems redundant. Regards, -- Shunsuke Sogame

On 10/21/07, shunsuke <pstade.mb@gmail.com> wrote:
BTW, why not `poly<T>`. `optional_` seems redundant.
I have already received requests (by gpd, when I showed him my first implementation few weeks ago) to provide also a non-nullable equivalent, so I think poly<T> should be reserved for it. BTW, the idea of the hand made vtable born in the discussion with gpd. My first implementation used just one function ptr to encapsulate all the behaviour (with a signature to fit all the methods), and was substantially less efficient than the current solution. Thanks Corrado -- __________________________________________________________________________ dott. Corrado Zoccolo mailto:zoccolo@di.unipi.it PhD - Department of Computer Science - University of Pisa, Italy --------------------------------------------------------------------------

AMDG Corrado Zoccolo <czoccolo <at> gmail.com> writes:
BTW, the idea of the hand made vtable born in the discussion with gpd. My first implementation used just one function ptr to encapsulate all the behaviour (with a signature to fit all the methods), and was substantially less efficient than the current solution.
You might find this useful if you want to generalize. http://tinyurl.com/2jap3m (I wrote it when I was trying to solve this same problem a year ago) Basic usage: #include <boost/vtable/make.hpp> #include <boost/vtable/pointer.hpp> struct print_function { typedef void (*function_pointer_type)(const void*); template<class T> stuct apply { static void value(const void* x) { std::cout << *static_cast<const T*>(x); } } }; boost::vtable::pointer< boost::vtable::make<boost::mpl::vector<print_function> >::type
table_type;
table_type table; table.set<double>(); double x = 2.5; void* vp = &x; table.find<function1>()(vp); // prints 2.5 In Christ, Steven Watanabe

Corrado Zoccolo wrote:
BTW, the idea of the hand made vtable born in the discussion with gpd. My first implementation used just one function ptr to encapsulate all the behaviour (with a signature to fit all the methods), and was substantially less efficient than the current solution.
Instead of a hand make vtable, why not this? struct impl_base { virtual void something(void*) = 0; }; template<typename T> struct impl { void something(void* p) { // do something useful } }; template<typename T> class poly { template<typename U> poly(const U& u) { new(&type_info) impl<U>; ... } typename boost::aligned_storage< sizeof(impl<T>), boost::alignment_of< impl<T> > >::type type_info; }; This simply assumes that all instances of impl have the same size and alignment.

On 10/22/07, Mathias Gaunard <mathias.gaunard@etu.u-bordeaux1.fr> wrote:
Corrado Zoccolo wrote:
BTW, the idea of the hand made vtable born in the discussion with gpd. My first implementation used just one function ptr to encapsulate all the behaviour (with a signature to fit all the methods), and was substantially less efficient than the current solution.
Instead of a hand make vtable, why not this?
struct impl_base { virtual void something(void*) = 0; };
template<typename T> struct impl { void something(void* p) { // do something useful } };
template<typename T> class poly { template<typename U> poly(const U& u) { new(&type_info) impl<U>; ... }
typename boost::aligned_storage< sizeof(impl<T>), boost::alignment_of< impl<T> > >::type type_info; };
This simply assumes that all instances of impl have the same size and alignment.
Because the vtables in C++ are not smart enough. If I make an hand made vtable, I can put not only function pointers, but also values inside it. This means that for example, I have to make a call through a function pointer to query if the object was allocated on heap or on stack, or if it has a no-throw copy constructor (all things that I can put directly in my hand made vtable). I think a valuable addition to c++0x would be "virtual constexpr" methods, i.e. virtual methods that are guaranteed to return compile time constants, but different classes in the hierarchy can return different values. This allows for a big optimization, i.e. the compiler can store the value of the constant into the vtable, and save an unpredictable call through a pointer. Corrado _______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- __________________________________________________________________________ dott. Corrado Zoccolo mailto:zoccolo@di.unipi.it PhD - Department of Computer Science - University of Pisa, Italy -------------------------------------------------------------------------- The self-confidence of a warrior is not the self-confidence of the average man. The average man seeks certainty in the eyes of the onlooker and calls that self-confidence. The warrior seeks impeccability in his own eyes and calls that humbleness. Tales of Power - C. Castaneda

AMDG Corrado Zoccolo <czoccolo <at> gmail.com> writes:
Because the vtables in C++ are not smart enough. If I make an hand made vtable, I can put not only function pointers, but also values inside it. This means that for example, I have to make a call through a function pointer to query if the object was allocated on heap or on stack, or if it has a no-throw copy constructor (all things that I can put directly in my hand made vtable).
There's another reason why a hand-made vtable is preferable in the general case when you can have arbitrary user-defined functions. A hand-made vtable allows you to take an arbitrary subset of the functions without adding more layers of indirection. In Christ, Steven Watanabe

Corrado Zoccolo wrote:
as well as providing a well known optimization technique to avoid dynamic allocation when the involved objects are small.
The problem with small object optimization is that you get the same issue that boost.variant has: it's hard to maintain the never-empty guarantee in operator=, because the copy constructor of a new value can throw and thus you lose the old value. I wonder, by the way, how boost.function solves that issue. Apart from that, what does optional_poly<T> give that optional< poly<T>
doesn't, apart from a small save of memory ? Maybe optional should be specialized, rather, to allow it to be more efficient for your type.

The problem with small object optimization is that you get the same issue that boost.variant has: it's hard to maintain the never-empty guarantee in operator=, Neither Boost.Any nor this optional_poly have a never-empty guarantee,
Mathias Gaunard wrote: though. Which makes = a lot easier, if you're satisfied with the Basic Guarantee. On the other hand, a poly would need a never-empty guarantee, thus making an optional<poly> much more complex than an optional_poly. Sebastian Redl

On 10/21/07, Sebastian Redl <sebastian.redl@getdesigned.at> wrote:
The problem with small object optimization is that you get the same issue that boost.variant has: it's hard to maintain the never-empty guarantee in operator=, Neither Boost.Any nor this optional_poly have a never-empty guarantee,
Mathias Gaunard wrote: though. Which makes = a lot easier, if you're satisfied with the Basic Guarantee. On the other hand, a poly would need a never-empty guarantee, thus making an optional<poly> much more complex than an optional_poly.
This is exactly the reason that made me start from optional_poly. It is a lot simpler to implement, with just basic exception safety guarantee. Anyway, optional_poly has strong exception safety guarantee for swap, so I think I could leverage it to implement poly<T> (with a larger overhead, and losing some opportunities to perform the small object optimization). Sebastian Redl
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- __________________________________________________________________________ dott. Corrado Zoccolo mailto:zoccolo@di.unipi.it PhD - Department of Computer Science - University of Pisa, Italy --------------------------------------------------------------------------

AMDG Mathias Gaunard <mathias.gaunard <at> etu.u-bordeaux1.fr> writes:
The problem with small object optimization is that you get the same issue that boost.variant has: it's hard to maintain the never-empty guarantee in operator=, because the copy constructor of a new value can throw and thus you lose the old value.
When I was trying to do this I only used the small object optimization for types that I knew to have a no-throw copy constructor (i.e. builtin types at the moment). In C++Ox this can be loosened to having a no-throw move constructor.
I wonder, by the way, how boost.function solves that issue.
It doesn't. Boost.Function can be empty and assignment for Boost.Function does not provide the strong guarantee of exception safety. In Christ, Steven Watanabe

Hi I've uploaded a new version of the library in the vault: * http://tinyurl.com/2og6st* It now provides also a new class (poly<T>) that maintains the never-empty guarantee. poly<T> and optional_poly<T> share a large part of their implementation, so I think it is sound to have both in the same library. On 10/22/07, Steven Watanabe <steven@providere-consulting.com> wrote:
When I was trying to do this I only used the small object optimization for types that I knew to have a no-throw copy constructor (i.e. builtin types at the moment). In C++Ox this can be loosened to having a no-throw move constructor.
My solution is more aggressive, allowing more optimization opportunities. Basically, if an object is small, it will be always stored in the small buffer when the poly is constructed. It will be allocated on heap only when the guarantee is at stake, e.g. during a swap between types that both lack a no-throw copy (it is sufficient that one of them have the no throw copy to avoid this allocation). Assignment operator is implemented by means of swap, so the same applies to it. I would like to take advantage also of movable types in the implementation of swap, so I'd like to see a move library submitted to boost. Corrado -- __________________________________________________________________________ dott. Corrado Zoccolo mailto:zoccolo@di.unipi.it PhD - Department of Computer Science - University of Pisa, Italy --------------------------------------------------------------------------

Corrado Zoccolo wrote:
Hi I've uploaded a new version of the library in the vault: * http://tinyurl.com/2og6st* It now provides also a new class (poly<T>) that maintains the never-empty guarantee. poly<T> and optional_poly<T> share a large part of their implementation, so I think it is sound to have both in the same library.
Hmm, it seems inherent that poly is DefaultConstructible(Nullable), IMHO. Why not introduce `nonnullable`? nonnullable< poly<T> > nonnullable< boost::shared_ptr<T> > BTW, poly<void> can't be "any"? Regards, -- Shunsuke Sogame

In my design, - optional_poly<T> is default constructible and nullable - poly<T> is not default constructible and not nullable The difference between the two is mainly in constructors and assignment operator. I don't think we can have a generic nonnullable<Z> that can select and forward only the correct constructors. You have to specialize it for every pointer-like class, so it doesn't simplify the developer work, and imposes longer names (on average) on the users: optional_poly<T> becomes poly<T> (now nullable) poly<T> becomes nonnullable<poly<T> > (nonnullability is now explicit) Making non-nullability explicit, though, adds the benefit that generic interfaces can now explicitly request non-nullable arguments without knowing the exact type of what's passed inside (e.g. poly vs. shared_ptr). The same can be obtained in a design with different names by means of a trait (is_nullable< >), and using enable_if, but it seems clumsier. I'm fine with either approach. Corrado On 11/2/07, shunsuke <pstade.mb@gmail.com> wrote:
Corrado Zoccolo wrote:
Hi I've uploaded a new version of the library in the vault: * http://tinyurl.com/2og6st* It now provides also a new class (poly<T>) that maintains the never-empty guarantee. poly<T> and optional_poly<T> share a large part of their implementation, so I think it is sound to have both in the same library.
Hmm, it seems inherent that poly is DefaultConstructible(Nullable), IMHO.
Why not introduce `nonnullable`? nonnullable< poly<T> > nonnullable< boost::shared_ptr<T> >
BTW, poly<void> can't be "any"?
Regards,
-- Shunsuke Sogame
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- __________________________________________________________________________ dott. Corrado Zoccolo mailto:zoccolo@di.unipi.it PhD - Department of Computer Science - University of Pisa, Italy -------------------------------------------------------------------------- The self-confidence of a warrior is not the self-confidence of the average man. The average man seeks certainty in the eyes of the onlooker and calls that self-confidence. The warrior seeks impeccability in his own eyes and calls that humbleness. Tales of Power - C. Castaneda

Corrado Zoccolo wrote:
I don't think we can have a generic nonnullable<Z> that can select and forward only the correct constructors. You have to specialize it for every pointer-like class, so it doesn't simplify the developer work,
Right, it would lead to complexity in order to know the result type of dereference. So, why not nonnullable_poly(or something). boost::any and boost::function are nullable but those names don't have "optional_" prefix. Regards, -- Shunsuke Sogame

On 11/2/07, shunsuke <pstade.mb@gmail.com> wrote:
[snip]
So, why not nonnullable_poly(or something). boost::any and boost::function are nullable but those names don't have "optional_" prefix.
The naming to adopt is always the more debated part in reviews. If I get chance to write the documentation and ask for formal review, we can bring this up within the review, and see what scheme is preferred by the majority of the boosters. For me, both schemes are fine, as long as we provide the functionality of both non-nullable and optional poly. Thanks, Corrado Regards,
-- Shunsuke Sogame
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- __________________________________________________________________________ dott. Corrado Zoccolo mailto:zoccolo@di.unipi.it PhD - Department of Computer Science - University of Pisa, Italy -------------------------------------------------------------------------- The self-confidence of a warrior is not the self-confidence of the average man. The average man seeks certainty in the eyes of the onlooker and calls that self-confidence. The warrior seeks impeccability in his own eyes and calls that humbleness. Tales of Power - C. Castaneda
participants (14)
-
Corrado Zoccolo
-
Dean Michael Berris
-
gchen
-
Jens Seidel
-
Joel de Guzman
-
Marco
-
Marco Costalba
-
Mat Marcus
-
Mathias Gaunard
-
Sebastian Redl
-
shunsuke
-
Simon Francis
-
Steven Wat
-
Steven Watanabe