Re: [boost] Proposal: Polymorphic Value Objects

Hello, I am trying to respond on the discussion (in the developer's list) on the indicated topic which were in 3-7 Sept. 2007. Not sure my e-mail will go by the right way (because of some technical troubles). But trying... Mathias Gaunard wrote:
Edd Dawson wrote:
I'm confused. Surely the whole point of shared_ptr is to relieve the programmer of the burden of worrying when its still used.
The problem is that with large programs you're not able to tell easily where it is being used. (also, you may create cycles by oversight, but that could be fixed eventually) The fact that it is automatically destructed when not used doesn't not mean that it can't be still used at wrong places, especially after code refactoring and modifications.
How are programs made more deterministic?
Because ownership is fixed to a scope. You thus perfectly know when the object will be constructed and destructed. With shared ownership, ownership is fully dynamic, and thus not determined.
These statements (from Mathias Gaunard) are very similar to those which I was trying to popularize in this news group a few years ago and first time even some 5-7 years ago. Though it seemed that I could not convince the majority (in particular that the shared pointers are in general unnecessary). But I am myself still convinced, although admit that shared pointer is acceptable in some rare exclusive circumstances. But, the content of Foo class, which Mathias Gaunard proposed in its first mail, is not clear for me. May be I am behind progress, but I do not know a way to make cloning pointer (or that Mathias' value object, but this seems to be the same in principle) to be non-intrusive. You anyway need virtual cloning function in each class of the hierarchy. I am trying to maintain an Internet page about these things, see http://cern.ch/ismirnov/safetl Regards Igor Smirnov

Igor.Smirnov@cern.ch wrote:
May be I am behind progress, but I do not know a way to make cloning pointer (or that Mathias' value object, but this seems to be the same in principle) to be non-intrusive. You anyway need virtual cloning function in each class of the hierarchy.
Boost.Any, for example, copies dynamically objects without having to modify their type. Here is a simplistic possible implementation for our case. template<typename T, typename D> T* clone_function(const T& t) { return new D(static_cast<const D&>(t)); } template<typename T> class Container { template<typename D> Container(const D& d) : obj(new D(d)), clone(clone_function<T, D>) { } // copy constructor, operator=, etc. ~Container() { delete obj; } T* obj; T* (*clone)(const T&); }; As I said earlier, this has a few flaws: - one word per object is wasted. Polymorphic objects already have one word that identifies their type (the pointer to the vtable) - it assumes that the static type of the object the container acquires is the same as its dynamic type.

Hi, Thanks for replies. On Fri, 21 Sep 2007, Mathias Gaunard wrote:
Igor.Smirnov@cern.ch wrote:
May be I am behind progress, but I do not know a way to make cloning pointer (or that Mathias' value object, but this seems to be the same in principle) to be non-intrusive. You anyway need virtual cloning function in each class of the hierarchy.
Boost.Any, for example, copies dynamically objects without having to modify their type.
Here is a simplistic possible implementation for our case.
template<typename T, typename D> T* clone_function(const T& t) { return new D(static_cast<const D&>(t)); }
template<typename T> class Container { template<typename D> Container(const D& d) : obj(new D(d)), clone(clone_function<T, D>) { }
// copy constructor, operator=, etc.
~Container() { delete obj; }
T* obj; T* (*clone)(const T&); };
As I said earlier, this has a few flaws: - one word per object is wasted. Polymorphic objects already have one word that identifies their type (the pointer to the vtable) - it assumes that the static type of the object the container acquires is the same as its dynamic type.
Thanks, Mathias. I see now how you can bypass assumption of "each stored type has virtiual clone function". But should the destructor of D and T be declared as "virtual" in order to make this work? If yes, this going to be "intrusive" detail anyway! The second of the "flaws" you listed seems to be bad. The first is not. Regarding the second one, is this correct to write: class T{...} class D: public class T {...} D my_derived_object; T& my_reference = my_derived_object; template<typename T> Container( my_reference); // and you initialize copy function for T for the object // which actually has type D. template<typename T> Container cnt1 = cnt; // and you silently construct // new object T from slice of D, which is scarcely expected. So this may be bad problem. Another point: I re-read your first mail with proposal and realized that I do not understand, why you propose value object but not smart pointer? How do you plan to access these objects and the functions of them? Through "."? How do you provide that the correct instance of virtual function is called, that is from type D? Why do you need this, at all? Indeed, the notation "->" is used to indicate possible call of virtual function, whereas "." is always understood as fixed call (if I understand correctly, correct me if not). So when you deal with polimorphic objects, it is better to do through (smart) pointers. Why do you want to mix this? I also can not undesrand the code from your first mail. Regards Igor

Igor.Smirnov@cern.ch write:
But should the destructor of D and T be declared as "virtual" in order to make this work? If yes, this going to be "intrusive" detail anyway!
Indeed, but this is part of the language.
Regarding the second one, is this correct to write:
class T{...} class D: public class T {...}
D my_derived_object; T& my_reference = my_derived_object; template<typename T> Container( my_reference);
[snip] That's not valid C++. Yet I still see what you mean, and I explained that problem several times months ago in my original message and in this thread.
I do not understand, why you propose value object but not smart pointer?
Since we deep-copy, we've got value semantics. Better make this a value than a pointer, then. Plus, it is well known that pointers are sources of unsafety. By completely hiding pointers from the interfaces, safety is gained.
How do you plan to access these objects and the functions of them? Through "."?
Unfortunately, operator. is not overloadable. So you'd have to use operator->. You could have seen that in the implementation and examples I provided.
How do you provide that the correct instance of virtual function is called, that is from type D?
The member functions must be virtual for them to be dynamically dispatched to the appropriate ones. It simply forward operator-> to the pointer to the base.
Why do you need this, at all?
There is a motivation part at the beginning of my first message.
Indeed, the notation "->" is used to indicate possible call of virtual function, whereas "." is always understood as fixed call (if I understand correctly, correct me if not).
operator. has nothing to do with "fixed calls". It is not the case, for example, when using references.
So when you deal with polimorphic objects, it is better to do through (smart) pointers. Why do you want to mix this?
Polymorphic value objects are a type of smart pointers, except that they have a value interface, not a pointer one.
I also can not undesrand the code from your first mail.
It's perfectly standard C++, and very simplistic. It's a very thin layer and easy to maintain. Have you ever looked at the code of a boost library? It's usually much more complicated.

I'm not sure if these polymorphic value objects are the same, but maybe you should look at Adobe's open source poly object: http://opensource.adobe.com/group__poly__related.html Tony

On 9/26/07, Gottlob Frege <gottlobfrege@gmail.com> wrote:
I'm not sure if these polymorphic value objects are the same, but maybe you should look at Adobe's open source poly object: http://opensource.adobe.com/group__poly__related.html
Tony
A recent paper on the implementation techniques used in Adobe's runtime-polymorphic value object library can be found in the MPOOL 2007 proceedings. If you are interested, please see: Mat Marcus, Jaakko Järvi and Sean Parent: *Runtime Polymorphic Generic Programming-Mixing Objects and Concepts in ConceptC++* <http://homepages.fh-regensburg.de/~mpool/mpool07/programme.html> Some additional details can soon be found in: @INPROCEEDINGS{jarvi:07:gpce, AUTHOR = {Jaakko J{\"a}rvi and Mat Marcus and Jacob Smith}, TITLE = {Library Composition and Adaptation using {C++} Concepts}, BOOKTITLE = {Generative Programming and Component Engineering (GPCE)}, YEAR = 2007, MONTH = OCT, LOCATION = {Salzburg, Austria}, NOTE = {To appear} } We have also given related presentations at C++ Connections 2005 and at BoostCon 2007: <http://opensource.adobe.com/wiki/index.php/Papers_and_Presentations> - Mat

Gottlob Frege wrote:
I'm not sure if these polymorphic value objects are the same, but maybe you should look at Adobe's open source poly object: http://opensource.adobe.com/group__poly__related.html
It's quite different. Mine allow to use objects of type Derived as if they were variables of type Base. Which is just OOP. From what I've read it seems Adobe ones allows to generate an interface on the fly from a C++0x and use it with types that comply to that interface, without any relation to inheritance or anything. That's more like "dynamic any".

On 9/27/07, Mathias Gaunard <mathias.gaunard@etu.u-bordeaux1.fr> wrote:
Gottlob Frege wrote:
I'm not sure if these polymorphic value objects are the same, but maybe you should look at Adobe's open source poly object: http://opensource.adobe.com/group__poly__related.html
It's quite different. Mine allow to use objects of type Derived as if they were variables of type Base. Which is just OOP.
From what I've read it seems Adobe ones allows to generate an interface on the fly from a C++0x and use it with types that comply to that interface, without any relation to inheritance or anything. That's more like "dynamic any".
-- Sorry if the research papers cited above misled you as to the capabilities Adobe poly<> library. Unfortunately, the end-user documentation is not yet complete. I hope to rectify this soon. In the meantime, I can set the record straight with respect to the statements that you made above. The poly<> library that currently ships is written in standard C++. No C++ '0x features are required--it compiles under VC8, gcc-4.20, etc. It does not require language support for Concepts. Poly<> supports the wrapping of specific interfaces. In fact, it could be viewed as a generalization of the any library, allowing any<> to be parametrized with an arbitrary "interface". Although poly<> shuns of OOP, it does provide for regular, polymorphic, value-types, without slicing (including support for downcasting, etc.). - Mat

Hi Igor! Igor.Smirnov@cern.ch wrote:
May be I am behind progress, but I do not know a way to make cloning pointer (or that Mathias' value object, but this seems to be the same in principle) to be non-intrusive. You anyway need virtual cloning function in each class of the hierarchy.
That's absolutely true, but if the user put their object in to a poly_obj at the earliest possible opportunity, this wouldn't be necessary. The static type is available at the point of construction and if you can keep hold of that (and you can), you won't run in to any problems. I can't imagine (at the moment) why someone would want to delay until they only have access to their object through a pointer or reference to base-type. It's good practice to put objects that require "management" of some kind in to some kind of other handler object as soon as they're constructed, anyway. Edd
participants (5)
-
Edd Dawson
-
Gottlob Frege
-
Igor.Smirnov@cern.ch
-
Mat Marcus
-
Mathias Gaunard