[iterator] std::sort on zip_iterator

(Resubmitting to Boost list because I did not receive any answers on boost-users.) I would like to sort two separate vectors of numbers, treating corresponding elements of the two vectors as tuples and sorting the tuples. In particular, I am only comparing the first elements of the tuples; that may or may not be relevant to my problem. An example program is: #include <vector> #include <algorithm> #include <iostream> #include <boost/tuple/tuple.hpp> #include <boost/iterator/zip_iterator.hpp> struct compare_first_elements_in_tuples { template <typename Tuple> bool operator()(const Tuple& a, const Tuple& b) const { return (a.template get<0>()) < (b.template get<0>()); } }; int main(int, char**) { size_t a_data[5] = {0, 2, 1, 2, 4}; size_t b_data[5] = {1, 1, 5, 3, 7}; std::vector<size_t> a(a_data, a_data + 5); std::vector<size_t> b(b_data, b_data + 5); std::cout << "Before:"; for (size_t i = 0; i < a.size(); ++i) { std::cout << " (" << a[i] << ", " << b[i] << ")"; } std::cout << std::endl; typedef std::vector<size_t>::iterator vec_iter; typedef boost::zip_iterator<boost::tuple<vec_iter, vec_iter> > zip_iter; std::sort(zip_iter(boost::make_tuple(a.begin(), b.begin())), zip_iter(boost::make_tuple(a.end(), b.end())), compare_first_elements_in_tuples()); std::cout << "After:"; for (size_t i = 0; i < a.size(); ++i) { std::cout << " (" << a[i] << ", " << b[i] << ")"; } std::cout << std::endl; return 0; } On gcc 4.0.1, the sort operation results in the element (2, 1) (a pair of corresponding elements in a and b) being duplicated, while the element (1, 5) does not appear in the result at all: Before: (0, 1) (2, 1) (1, 5) (2, 3) (4, 7) After: (0, 1) (2, 1) (2, 1) (2, 3) (4, 7) I suspect the problem is related to the fact that zip_iterator does not return a "real" reference when dereferenced. Am I mistaken about this? Is the code above supposed to work? If not, is there an alternative way to sort one sequence while swapping elements in another in a corresponding way? I am not able to join the two input sequences into a single sequence of pairs because of other factors in the use case for this code. Thank you for your help. -- Jeremiah Willcock

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Jeremiah Willcock Sent: Tuesday, May 05, 2009 2:46 AM To: boost@lists.boost.org Subject: [boost] [iterator] std::sort on zip_iterator
(Resubmitting to Boost list because I did not receive any answers on boost-users.)
I would like to sort two separate vectors of numbers, treating corresponding elements of the two vectors as tuples and sorting the tuples. In particular, I am only comparing the first elements of the tuples; that may or may not be relevant to my problem. An example program is:
#include <vector> #include <algorithm> #include <iostream> #include <boost/tuple/tuple.hpp> #include <boost/iterator/zip_iterator.hpp>
struct compare_first_elements_in_tuples { template <typename Tuple> bool operator()(const Tuple& a, const Tuple& b) const { return (a.template get<0>()) < (b.template get<0>()); } };
int main(int, char**) { size_t a_data[5] = {0, 2, 1, 2, 4}; size_t b_data[5] = {1, 1, 5, 3, 7}; std::vector<size_t> a(a_data, a_data + 5); std::vector<size_t> b(b_data, b_data + 5); std::cout << "Before:"; for (size_t i = 0; i < a.size(); ++i) { std::cout << " (" << a[i] << ", " << b[i] << ")"; } std::cout << std::endl; typedef std::vector<size_t>::iterator vec_iter; typedef boost::zip_iterator<boost::tuple<vec_iter, vec_iter> > zip_iter; std::sort(zip_iter(boost::make_tuple(a.begin(), b.begin())), zip_iter(boost::make_tuple(a.end(), b.end())), compare_first_elements_in_tuples()); std::cout << "After:"; for (size_t i = 0; i < a.size(); ++i) { std::cout << " (" << a[i] << ", " << b[i] << ")"; } std::cout << std::endl; return 0; }
On gcc 4.0.1, the sort operation results in the element (2, 1) (a pair of corresponding elements in a and b) being duplicated, while the element (1,
Hello Willcock, I also hope your code would work as your desire. That is an expection natural for a lib to the extreme of elegance and power. But I'm afraid it won't. I have ever similar experience with some iterator adaptor, but not zip_iterator, and have a similar question and similar result. But I just cannot remember what exactly it was at the present. I think your suspection is eaxctly what the matter is. As soon as I get further information that would be of help, I will let you know. B/Rgds Max 5)
does not appear in the result at all:
Before: (0, 1) (2, 1) (1, 5) (2, 3) (4, 7) After: (0, 1) (2, 1) (2, 1) (2, 3) (4, 7)
I suspect the problem is related to the fact that zip_iterator does not return a "real" reference when dereferenced. Am I mistaken about this? Is the code above supposed to work? If not, is there an alternative way to sort one sequence while swapping elements in another in a corresponding way? I am not able to join the two input sequences into a single sequence of pairs because of other factors in the use case for this code. Thank you for your help.
-- Jeremiah Willcock _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (2)
-
Jeremiah Willcock
-
Max