Prev: Is there any standard/guarantees for exception safety in STL operations?
Next: problem with partial ordering of classes
From: Thiago A. on 26 Jul 2010 23:41 > I fail to see the very advantage of a new key word > (with all it's implications - can I/need I specialize > templates for it?) compared to the current library > solution. Or shorter: What is the advantage of > > unique* T > > over > > std::unique_ptr<T> * Better syntax, without templates and includes * Better error messages * Fast code? * Array compatibility void F(const Resource* p, int n) {... } std::vector<std::unique_ptr<const Resource>> v; //error (maybe it works with reinterpret_cast?) F(&v[0], v.size()); I started to think about this subject because of syntax questions, and because I think pointer ownership is a basic concept of the language. We know that the language evolutes first through libraries and this can make the language less expressive and difficult to use. Sometimes the language changes to suport better something used as a library. The unique_ptr itself started with auto_ptr and now using the move semantics. We have the null_ptr and bool which started as NULL and BOOL. First I imagined a direct syntax conversion between unique_ptr<T> and unique T *, however with good error messages. This raised the "deleter" question. "Where the deleter is specified?" Then I tried a "flat" version without the deleter and the operator delete with an extra optional argument "deleter". Maybe a template specialization could be beneficed with a type modifier, maybe not; I confess I don�t have a real template problem/ motivation. I haven�t used the unique_ptr so much, but if I had to choose a smart pointer for RAII I would choose the unique_ptr. I still not sure if I will change the normal pointer style for unique pointers. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Daniel Krügler on 26 Jul 2010 23:45 On 27 Jul., 07:31, Dragan Milenkovic <dra...(a)plusplus.rs> wrote: > On 07/26/2010 07:45 PM, Daniel Kr�gler wrote: > > > On 25 Jul., 16:27, Dragan Milenkovic<dra...(a)plusplus.rs> wrote: > > > [..] > > >> I didn't give thought or searched for existing discussions > >> on this topic, but there is another, much more important item > >> that you forgot... The support for covariant return types... > > > Since you are already changing the subject: It might be > > helpful, if you would be more specific in this point as > > well, because covariant return types are supported in > > C++. I assume you have something similar in mind > > as discussed in the older thread "Treating Foo<T>* as > > Foo<const T>*",[1] extended to "Treating Foo<Derived>* as > > Foo<Base>*" or to "Treating Foo<Derived> as > > Foo<Base>" but that is just guessing. > > I assumed that OP meant to incorporate shared_ptr into > the language as opposed to being a library. He refers > to it as a modifier, although this would not be it's > nature. At least this is how I understood it... I think you understand the OP pretty well, but I did not understand your remark well ;-) - sorry for that! > I don't have any proposal and can live with the current > state of things. I was simply stating one additional > advantage so he can give more thought to his proposal > (I hope that came out right). After rereading your message I agree that you were pretty clear. > Disclaimer: I will now be plain silly: > > std::shared_ptr<Foo> foo = std::make_shared<Foo>(); > > Foo $ foo = std::make_shared<Foo>(); > > ... end of silliness. I see, but I wonder which would be the compiler rules in regard to "sharing"? It seems that uniqueness constraints are easier to check than sharing constraints. > And about treating Foo<Derived> as Foo<Base>; it can > somewhat be solved by a conversion operator, right? Typical implementations do this by providing a converting constructor, yes. This is the way unique_ptr and shared_ptr are specified. This does not allow for binding a *pointer* or reference of type unique_ptr<Derived> to a corresponding object of type unique_ptr<Base>, though. While it is - with some efforts - possible to realize that in regard to cv qualifications (as shown in the referenced thread), this is not so easy to realize in a completely general way in regard to inheritance relations (but I haven't tried it yet). > It's just that I sometimes wish that some conversions > were transitive (can be chained automagically)... :-) > and I don't necessarily speak about templates. I understand this, but I'm not sure that the resulting increase of the complexity of the type system is worth the effort. IMO it is similar or even more drastic than allowing to overload the operator., see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1671.pdf Alternative approaches are to allow for user-providing conversion operators, as shown in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2200.pdf Greetings from Bremen, Daniel Kr�gler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Thiago A. on 26 Jul 2010 23:40 > > > - Better error message generated by compiler > > Can you show a plausible compiling error with std::unique_ptr that > would be improved with your suggestion? Any error will expand the template and give us at least 10 lines of error message. struct Myclass { unique_ptr<Resource> p; }; Myclass a; Myclass b; a = b; -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Andy Venikov on 27 Jul 2010 06:13 Thiago A. wrote: >> I fail to see the very advantage of a new key word >> (with all it's implications - can I/need I specialize >> templates for it?) compared to the current library >> solution. Or shorter: What is the advantage of >> >> unique* T >> >> over >> >> std::unique_ptr<T> > * Better syntax, without templates and includes I actually find unique_ptr<int> a pretty nice way of describing what you want. I don't think that the syntax argument is a strong argument. > * Better error messages This is in my view the best and only argument for unique type modifier. > * Fast code? I think that modern compilers will compile all operations on unique_ptr<T> as though it was T*, so the run-time speed will be extremely efficient. > * Array compatibility > void F(const Resource* p, int n) {... } > std::vector<std::unique_ptr<const Resource>> v; > //error (maybe it works with reinterpret_cast?) > F(&v[0], v.size()); Well, you just broke the uniqueness of the pointers by trying to pass them to F while at the same time keeping them in the vector. Not unique anymore. <snip> Andy. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Dragan Milenkovic on 28 Jul 2010 05:21 On 07/27/2010 04:45 PM, Daniel Kr�gler wrote: [snip] >> And about treating Foo<Derived> as Foo<Base>; it can >> somewhat be solved by a conversion operator, right? > > Typical implementations do this by providing a converting > constructor, yes. This is the way unique_ptr and shared_ptr > are specified. This does not allow for binding a *pointer* > or reference of type unique_ptr<Derived> to a corresponding > object of type unique_ptr<Base>, though. But this is not possible even with simple pointers. They too need to be converted from Derived * to Base *. I cannot even think of many differences between a smart pointer and a pointer (except for covariant returns, and something related to template resolution)... I guess this tells that smart pointers have been done right. :-) [snip] > >> It's just that I sometimes wish that some conversions >> were transitive (can be chained automagically)... :-) >> and I don't necessarily speak about templates. > > I understand this, but I'm not sure that the resulting increase > of the complexity of the type system is worth the effort. > IMO it is similar or even more drastic than allowing to > overload the operator., see [snip] One of my free-time designs evolved into something like this: class Foo_impl {blabla}; class Bar_impl : public Foo_impl {blabla}; And these classes are then passed around and composed into other classes through shared_ptrs. On the other side, the public interface contains concrete classes Foo and Bar which wrap shared pointers and provide public functions. I found this design very nice because it greatly simplifies the public interface, separates the implementation (which can and was refactored a few times without changing the public interface), allows for operators such as &&, ||. The first impression is that it increases complexity, but it actually made my life easier. Of course, I wanted to convert Bar into Foo. This works nice until there comes Joe. (Joe_impl inherits Bar_impl). struct Bar { operator Foo () const; }; struct Joe { operator Bar () const; operator Foo () const; // Joe no like Foo... }; This is just a sample. The main reason for me wanting some kind of cascade (disclaimer: I have not given thought about what and how to do it), is that I renamed and changed the design all the time, trying how the new one would behave. Much time was lost on things that I would call secondary, such as converting Joe to Foo... That's it. Actually, as this was my last-year work, I just checked... there are no conversion operators left. I guess I removed them all until the design becomes stable; or perhaps changed the design to not require them. But I'm sure I experimented with this stuff. I even had Foo_const, Bar_const variants which added to the complexity of casts. Also I tried making templates and using enable_if, etc... Now I will stop with the boring stuff... thanks for reading. -- Dragan [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 Prev: Is there any standard/guarantees for exception safety in STL operations? Next: problem with partial ordering of classes |