问题
I'm a bit confused about the difference in requirements of operator<
const
qualifier for std::sort and std::stable_sort. Suppose a simple structure:
#include <vector>
#include <algorithm>
struct Custom {
bool operator<(const Custom& custom) /* const */{
return true;
};
};
Everything is ok if we try to compile and run this code:
int main() {
std::vector<Custom> values(3);
std::sort(values.begin(), values.end());
return 0;
}
But this code with std::stable_sort
failed to compile:
int main() {
std::vector<Custom> values(3);
std::sort(values.begin(), values.end());
return 0;
}
Here's an error stack trace:
In file included from /usr/include/c++/5/bits/stl_algobase.h:71:0,
from /usr/include/c++/5/bits/char_traits.h:39,
from /usr/include/c++/5/ios:40,
from /usr/include/c++/5/ostream:38,
from /usr/include/c++/5/iostream:39,
from temp.cpp:1:
/usr/include/c++/5/bits/predefined_ops.h: In instantiation of ‘bool __gnu_cxx::__ops::_Val_less_iter::operator()(_Value&, _Iterator) const [with _Value = const Custom; _Iterator = __gnu_cxx::__normal_iterator<Custom*, std::vector<Custom> >]’:
/usr/include/c++/5/bits/stl_algo.h:2050:14: required from ‘_ForwardIterator std::__upper_bound(_ForwardIterator, _ForwardIterator, const _Tp&, _Compare) [with _ForwardIterator = __gnu_cxx::__normal_iterator<Custom*, std::vector<Custom> >; _Tp = Custom; _Compare = __gnu_cxx::__ops::_Val_less_iter]’
/usr/include/c++/5/bits/stl_algo.h:2522:26: required from ‘void std::__merge_without_buffer(_BidirectionalIterator, _BidirectionalIterator, _BidirectionalIterator, _Distance, _Distance, _Compare) [with _BidirectionalIterator = __gnu_cxx::__normal_iterator<Custom*, std::vector<Custom> >; _Distance = long int; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’
/usr/include/c++/5/bits/stl_algo.h:2782:34: required from ‘void std::__inplace_stable_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Custom*, std::vector<Custom> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’
/usr/include/c++/5/bits/stl_algo.h:4863:28: required from ‘void std::__stable_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Custom*, std::vector<Custom> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’
/usr/include/c++/5/bits/stl_algo.h:4897:36: required from ‘void std::stable_sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator<Custom*, std::vector<Custom> >]’
temp.cpp:15:45: required from here
/usr/include/c++/5/bits/predefined_ops.h:71:22: error: no match for ‘operator<’ (operand types are ‘const Custom’ and ‘Custom’)
{ return __val < *__it; }
So my question is: Is it just the consequence of technical implementation details or there exists some objective arguments in favor of such behavior?
回答1:
[alg.sorting]/2
Compare
is a function object type (20.9). The return value of the function call operation applied to an object of typeCompare
, when contextually converted tobool
(Clause 4), yieldstrue
if the first argument of the call is less than the second, andfalse
otherwise.Compare comp
is used throughout for algorithms assuming an ordering relation. It is assumed thatcomp
will not apply any non-constant function through the dereferenced iterator.[alg.sorting]/3 For all algorithms that take
Compare
, there is a version that usesoperator<
instead. That is,comp(*i, *j) != false
defaults to*i < *j != false
.[res.on.functions]/1 In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.
Emphasis mine. Your program exhibits undefined behavior by way of supplying to a standard library function a component that doesn't meet the function's requirements.
By the way, clang rejects both std::sort
and std::stable_sort
.
来源:https://stackoverflow.com/questions/45905122/requirement-of-operator-constness-in-stdstable-sort