Topic: should set<T,cmp1>::iterator and set<T,cmp2>::iterator be of
Author: dants@cs.huji.ac.il (Dan Tsafrir)
Date: Fri, 11 Nov 2005 05:40:53 GMT Raw View
wade@stoner.com wrote:
> Dan Tsafrir wrote:
>
>
>>[wants set<T,C1,A1>::iterator to be the same as set<T,C2,A2>::iterator]
>
>
> A1 != A2 would mean that implementations cannot efficiently support
> multiple, simultaneous pointer/reference models (proxy references, for
> instance).
I'm not sure I understand:
If by any chance your answer involves not just changing of allocators
(same std::set code using different allocator templates-parameters),
but rather, a _specialized_ version of say set<T,C1,A1> (re-implementation
of the entire std::set), then please note my suggestion only relates
to the standard template library (the actual classes etc.) that ships
with your distribution. Other parties are still free to decide whether
the iterators they define are of the same type or not.
Recall that (as I said earlier) iterators of std::set<T,*,*> are
already of the same type for STLPort, GCC's STL, Comeau's STL...
This is not just some crazy idea ;)
Putting specializations involving comparator/allocator aside, I can't
see a problem in set<T,*,*>::iterator being of the same type. There's
nothing to stop same type iterators from being, say, stack variables
pointing to objects that were allocated using different allocators.
>
> C1 != C2 would mean that implementations cannot efficiently change the
> underlying structure for different comparisons. If my implementation
> supports partition_traits<C1>::max_size, and that tells me that
> set<T,C1> will never have more than eight values, I may use a
> specialized structure for small sets which is very different from (and
> more efficient than) the RB tree I use for larger sets.
Once again, I'm only talking about the container classes that come with
your compiler distribution. Not about every conceivable specialization
users may wish to implement.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: dants@cs.huji.ac.il (Dan Tsafrir)
Date: Tue, 8 Nov 2005 05:19:43 GMT Raw View
Greg Herlihy wrote:
> Along these lines it is possible to imagine a Container algorithm to,
> say, apply a function to each item in a Container:
>
> template <class Container, class Function>
> void for_each_item( Container c, Function f)
> {
> std::for_each(c.begin(), c.end(), f);
> }
Unfortunately, I think this doesn't solve the original problem :(
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: dants@cs.huji.ac.il (Dan Tsafrir)
Date: Tue, 8 Nov 2005 05:19:36 GMT Raw View
Greg Herlihy wrote:
> The idea here as I understand it is to guarantee that two containers of
> the same type each holding the same type of object would then also have
> to offer iterators of matching types. The benefit by mandating what are
> essentially interchangeable iterators, between say:
>
> std::set<int, std::less<int> >
>
> and a:
>
> std::set<int, std::greater<int> >
>
> is that a program could then treat each container as the same type for
> the purposes of iterating its contents.> While generic programming
> certainly has value, distinct typing has some value as well. In this
> case, the distinct iterator types make it less likely that the program
> would ever compare iterators from different containers or - worse - try
> to iterate between two such mismatched iterators.
Please note that in the current situation, you don't enjoy neither...
- you can't really write:
std::set<int,std::greater<int> > s;
std::set<int>::iterator i = s.begin();
because this is not portable and will only work for some distributions,
- but in these distributions, if you did use such code, the compiler will
not warn you you've done something "wrong", and will also obviously not
help you if you somehow tried to iterate between two mismatched iterators.
Making the choice explicit in the standard (either set<int,A>::iterator /
set<int,B>::iterator are of the same type, or their not) will insure you
enjoy at least one alternative (being more generic, or more "safe"). So
with respect to your argument, the real question seems to be which
alternative do you prefer to be standardized?
I tend to think the benefits of the generic alternative far outweigh that
of the "safer" alternative. I keep using the quotes in the latter because
when taking your view to the extreme, one might argue that the language
should not allow an algorithm like std::copy() or std::for_each() to exist
altogether, because, as you say, they might run the risk of iterating
between two mismatched iterators.
But more importantly, I think the generic alternative is better because
conceptually, in terms of iteration, the specific details of the comparator
used by the container are simply "implementation details" that should be
hidden: Recall that iterators are actually an abstraction of pointers; and
indeed, had you used two (non-template) red-black trees of ints, you could
have used the _same_ loop to iterate through the two of them, regardless of
the specific order in which the ints were inserted into the tree. Why
shouldn't this be the case with parameterized RBtrees too?
My point is probably clearer if you consider allocators. Do you honestly
think that the validity if this code:
std::set< int, std::greater<int>, allocA > s;
std::set< int, std::greater<int>, allocB >::iterator i = s.begin();
should be implementation defined?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]