On Tue, Oct 16, 2012 at 3:25 AM, Oswin Krause <Oswin.Krause@ruhr-uni-bochum.de> wrote:
Hi,
I often have problems which look a bit like this:
//example code, only for problem statement
//std::vector<bool> chosen only because it is no container :). If this is too silly for you,
//think about a matrix interpreted as range of row-vectors.
std::vector<bool> myContainer;//does only have proxy iterators.
std::vector<double> myDistances; //stores for every element in myContainer a distance
//now i want to to sort the elements of both ranges in place
//as if they were in a hypothetic range std::vector<std::pair<bool, double> >
//and sort them by the second part:
boost::sort(make_key_value_range(myContainer,myDistances));//bam, not allowed
I omited the definition of make_key_value_range but it should be clear that this returns a proxy range with writable iterators and reference type similar to std::pair<std::vector<bool>::reference,double&> for which swap is overloaded to do the right thing.
You should be able to equally well use zip_iterator's, or, if supported by Boost.Range, something like a make_zip_range.
This is not allowed by the standard as boost::sort calls std::sort which in turn requires random_access_iterators - and they disallow proxy references.
Ugh, yes :(
This issue is AFAIK resolved with C++11 but some of us still need to support C++03 - and I am really annoyed by this problem.
Hmmm...how is this resolved in C++11? AFAIK, C++11 still uses the old archaic iterator categories and requires a real C++ reference as the reference type of forward iterators.
The thing is: this will compile on most compilers. One could just lie about the iterator category, saying it is a random_access_iterator and even VC would be happy with it. However it could just break randomly on a new compiler without warning or has severe performance issus (for example gcc works, but completely ignores my nicely defined swap and instead does a triangle copy :-( ).
So how can one resolve this issue? I have the problem, that i need to do this in-place, since copying would result in std::bad_alloc almost surely. Also the above single line of code just looks that nice, that i just want to have it this way.
So, how do you resolve this issue? is there maybe some boost library capable of getting this done? e.g. boost.betterSTL? :-).
I agree, this is a deficiency in the standard. Unfortunately, maybe the only thing you can do to guarantee this works in a portable way is to code up your own introsort [1] implementation :/
- Jeff
[1]
http://en.wikipedia.org/wiki/Introsort