This is the mail archive of the libstdc++@sourceware.cygnus.com mailing list for the libstdc++ project. See the libstdc++ home page for more information.
Nathan Myers <ncm@cygnus.com> wrote: : Oleg wrote: : > Nathan Myers <ncm@cygnus.com> wrote: : > : Oleg Zabluda wrote: : > : > Ryszard Kabatek <rysio@rumcajs.chemie.uni-halle.de> wrote: : > : > : I wrote an iterator class for std::vector<> and std::basic_string<>. [...] : > : > : template<typename _Up> : > : > : _Iterator(const _Iterator<_Tp, _Dist, _Up*, _Up&>& __rhs); : > : > : > : > That's very unsafe. This will provide a conversion not only : > : > from iterator to const_iterator but many other undesirable : > : > _implicit_ conversions as well. For example, : > : > vector<Derived>::iterator --> vector<Base>::iterator. : > : > : No, this is not a conversion from a const_iterator, it's just : > : a copy of a const reference to an ordinary iterator. : > : > I think you are mistaken. : Of course you are right. : > BTW. Now that I look at this again, I see other problems with : > this piece of code. First of all, technicaly, this is not just : > a copy constructor, therefore the comment is incorrect. Second of all, : > there is no matching [non-copy] assignment operator. : In fact it's not a copy constructor at all; given this definition the : compiler would still automatically generate a copy constructor. I agree : that we don't want any promiscuously polymorphic copy constructors for : vector and string, because the types they store cannot be used : polymorphically. : The assignment would also be compiler-generated. Right. However, let me reiterate the point I wanted to make. We need to define a [non-copy] constructor iterator->const_iterator. Therefore we must not forget to define a [non-copy] assignment iterator->const_iterator as well. If we don't, the [non-copy] construction will not be equivalent to a construction followed by the [non-copy] assignment. Although such a [non-copy] assignment might happen automatically, due to implicit conversion of the right-hand side, it will involve one more user-defined conversion, compared to the [non-copy] construction. If, for example, the right-hand side was already a result of an implicit user-defined conversion, the [non-copy] assignment will not happen, because a compiler will not apply two implicit user-defined conversions in a row. There are probably template argument deduction issues as well. [....] : > Besides, if : > we derive one from the other, and not explicitly ban the slicing, : > we will introduce other bizarre _implicit_ conversions, like : > iterator* --> const_iterator* (compare to T** --> const T**). : > : > In short, we'll never drive Plauger out of business if we : > gonna repeat his mistakes :-) : OK, agreed. I hadn't studied his mistakes beyond his having : derived in the wrong direction (!). I would like to do some : experiments with private derivation and some "using" exposures. : The nice properties of built-in promotion are not to be given : up lightly. Ok. Let us know how it goes. In the meantime I'll implement the straightforward one. I'll try tomorrow, on Tuesday. This will give us one more implementation to compare things against. : > We could derived them from a common base, but this will : > introduce a vtbl and we don't want that. : Right, maybe. Anyway, for something as simple as a pointer : wrapper I'm not sure implementation-inheritance would buy : you anything anyway, besides built-in promotion. I agree. I think the added benefits will be well worth the code duplication. Let me reiterate them: 1. Plain, sane, easy-to-understand design. Since it's a free software project, keeping it simple and easy-to-understand is a virtue by itself, because it increases the pool of people capable and willing to contribute. 2. The data member in the const_iterator will be a pointer to const. 3. No implicit template converting constructors or template assignment operators. 4. iterators will be real classes with the names that a user expects. Therefore sane and actualy useful error messages. 5. vector<char>::iterator and basic_string<char>::iterator will be different and unrelated types. Hopefully, with appropriate typedefs, the actual code will actually be 90% identical. If properly documented, this will almost completely mitigate the consequences of the code duplication. Oleg.