Recently, I began to prefer the free functions std::next and std::prev to explicitly copy and increase / decrease iterators. Now I see strange behavior in a rather specific case, and I would appreciate any help in demystifying it.
I have an interpolation / extrapolation function working on boost::any_range some X_type . Full range type definition:
boost::any_range < const X_type, boost::random_access_traversal_tag, const X_type, std::ptrdiff_t >
any_range in this particular case is assigned from iterator_range containing two pointers to const X_type , which serves as a representation of X_type about half of the data() a vector<char> .
Compiling my application in MSVC 2010, everything works fine. Compiling the same code in MinGW g ++ 4.7.0, it seemed to hang in one specific place, which I then narrowed down to this (slightly abbreviated):
// Previously ensured conditions: // 1) xrange is nonempty; // 2) yrange is the same size as xrange. auto x_equal_or_greater = std::lower_bound(std::begin(xrange),std::end(xrange),xval); if (x_equal_or_greater == std::end(xrange)) { return *yit_from_xit(std::prev(x_equal_or_greater),xrange,yrange); }
While executing the code in gdb, I found that it was not stuck, it just took a lot of time to return from the only call to std::prev , which in libstdC ++ is implemented in terms of std::advance and, ultimately, += .
Just replacing the return string with:
auto xprev=x_equal_or_greater; --xprev; return *yit_from_xit(xprev,xrange,yrange);
Performance is great again, and there is virtually no lag.
I am aware of the overhead of using style- any_range iterators (those of any_range ), but even in this case, two cases above that really have to bear such different costs? Or am I doing something wrong?