
13 Feb
2013
13 Feb
'13
11:04 a.m.
On 02/11/2013 09:48 PM, Vicente J. Botet Escriba wrote: > Le 11/02/13 19:15, Ralph Tandetzky a écrit : >> On 02/10/2013 10:27 AM, Vicente J. Botet Escriba wrote: >>> Le 10/02/13 03:04, Vicente J. Botet Escriba a écrit : >>>> Le 08/02/13 16:16, Ralph Tandetzky a écrit : >>>>> Hi, >>>>> >>>>> is there any interest in a copy-on-write pointer implementation? I >>>>> wrote a cow_ptr<T> template class for C++11 which has the >>>>> following use cases: >>>>> ... >>>>>>> 3. You can add cloning to a class hierarchy from the outside. With >>>>>>> cow_ptr<Base> a( new Derived1 ); >>>>>>> cow_ptr<Base> b( new Derived2 ); >>>>>>> cow_ptr<Base> c; >>>>>>> c = a; // performs a shallow copy. >>>>>>> c->doSomething(); // makes a deep copy of a as a >>>>>>> Derived1 class. >>>>>>> // There is no slicing involved. >>>>>>> you copy Base objects polymorphically. The class Base can even >>>>>>> be abstract here. It is only required that Derived1 and Derived2 >>>>>>> be CopyConstructible. >>>>>>> >>>>>> >>>>>> It seems to me that the copy of polymorphic object works only >>>>>> with the help of the user and that the following should be >>>>>> mentioned as a limitation >>>>>> >>>>>> Base* ba = new Derived1; >>>>>> cow_ptr<Base> a( ba ); >>>>>> cow_ptr<Base> c; >>>>>> c = a; // performs a shallow copy. >>>>>> c->doSomething(); // couldn't makes a deep copy of a >>>>>> as a Derived1 class as the type has been lost. >>>>>> // There is a slicing involved. >>>> >>>> In the DefaultCloner there is an assertion >>>> assert( typeid( *p ) == typeid( const T& ) ); >>>> which would be violated in the line you marked. So you'll notice >>>> that during debugging when the copy is performed. There's no way to >>>> check that at compile-time unfortunately. > Ok. So typeid( *p ) == typeid( const T& ) is a precondition of the > constructor from a Y*. I find this quite unfortunate. Which is the > advantage this provide to the user? Better performances? if yes where? The advantage relative to what? I assume in comparison to make_cow. Well, there are several advantages: 1. You can construct from a pointer that points to something already allocated. You do not need to allocate and copy. 2. You have a custom copier/cloner and custom deleter. The assertion performes automatic checking in debug mode. In release mode everything can run at full speed. >>>> >>> If this is confirmed, I see it as a show-stopper, and the cloning >>> strategy must be redefined. >>> >>> I don't see any relational operators. Is this intentional? >> >> To a degree. It's not totally obvious, if only the pointers will be >> compared, or if pointers are equal, if the pointed-to objects will be >> compared for equality as well. I'd prefer the first variant and I >> will add them in the next revision. > Could your class store nullptr? > Does your class have value semantics or pointer semantics? > IMHO, it should have value semantics and the comparison should be made > on the stored value. That's a good question. Right now I tend to prefer genuine value semantics, because right now I don't see a point in making it nullable. I never had this usecase. Then cow_ptr would not be appropriate as name anymore. In order to make the possibly polymorphic behaviour of the pointees more visible in the name of the class, clone_on_write<T> might be better then plain copy_on_write<T>. What about a reset(U*) member function ? >> This stuff can be done with the constructors and the assignment >> operators. So, strictly speaking there's no need for it. You might >> get a bit better performance with reset() though. (Is performance >> actually the reason for shared_ptr and unique_ptr to provide a >> reset() function?) At first I wanted to keep the class interface >> simple. I might add it in the future. Are there compelling reasons to >> add it now? >> > I suspect that if the operation can be implemented with better > performances than using constructor and assignment it is a compelling > reason. Ok, well then, I will implement it soon. > Best, > Vicente Thanks, Ralph