Douglas Paul Gregor <[EMAIL PROTECTED]> writes: > On 26 Mar 2003, Anthony Williams wrote: > > It strikes me that if you dereference n iterators, you have n values, and > > the most natural way to store them is a tuple. Doing anything other than > > returning this tuple seems to me just complicating the usage. > > I would agree if tuples and argument passing were more closely linked, > i.e., if passing a tuple to a function meant that the tuple would be > automagically unpacked into separate arguments. But that's not the case, > so the introduction of tuples as the return type makes it harder to then > apply a function object to the values.
Whereas having the iterator apply a functor to the values makes it harder to apply a function object that accepts a tuple. > For instance, consider an iterator > that adds the values from two other iterators (with the combining > iterator): > > make_combining_iterator(first.begin(), second.begin(), > std::plus<int>()); > > With the tuple iterator, you need to either (a) write your own > std::plus-like function object that accepts a tuple<int, int> instead of > two int parameters or (b) use something like Aleksey's apply (?) function > that unpacks a tuple and applies the separate arguments to a function > object. And what's so difficult in doing that? The code has to be there as part of the current combining iterator anyway, so it's not too bad to have to split it off to a separate functor. You could make a wrapper function that applied it as well as the supplied functor: make_combining_transform_iterator_with_args(first.begin(), second.begin(), std::plus<int>()); which does: make_combining_transform_iterator(first.begin(), second.begin(), split_tuple_and_call(std::plus<int>())); > > How do you write the following with your combining iterator? (TupleIt is a > > supposed generalisation of my PairIt which returns a tuple rather than a > > pair) > [snip] > > std::sort(makeTupleIterator(first.begin(),second.begin(),third.begin()), > > makeTupleIterator(first.end(),second.end(),third.end()), myCompareFunc); > > makeTupleIterator(first.begin(), second.begin(), third.begin()) is > equivalent to > make_combining_iterator(first.begin(), second.begin(), third.begin(), > &boost::tuples::make_tuple<int, int, int>); that'd have to be make_tuple<int&,int&,int&> for sort, so that you can write back to your vectors. However, then copying the tuple doesn't create a true copy; it still has references to the original, and a swap along the lines of X tmp=a; a=b; b=tmp; (such as might be used as part of the implementation of std::sort) would then not work. The tuple returned would have to be a custom tuple type, much as the return type of derefencing my PairIt is a custom pair type, in order to ensure that things like std::sort work OK, so it would not be as simple as using boost::tuples::make_tuple, but it could be done with an equivalent functor. The beauty of having this the main interface is that such reference vs value details can be taken care of automatically depending on the iterator category, whereas if you try and do it retrospectively with a functor, then you have to specify whether to use references or values, which can be error prone --- I expect that using make_tuple<int,int,int> will compile, yet the vectors will remain unsorted. It appears to me that we need both, and we can have both by simply providing helper functions either way. However, I'm inclined to think it better to provide the tuple-based dereferencing as default, with a custom functor (and helper function) to provide the split into function-call arguments, rather than vice-versa. Anthony -- Anthony Williams Senior Software Engineer, Beran Instruments Ltd. Remove NOSPAM when replying, for timely response. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost