following this question , I tried to copy paste the example found here in VS2010 :
#include <algorithm>
#include <vector>
#include <iostream>
struct S
{
int number;
char name;
S ( int number, char name )
: number ( number ), name ( name )
{}
// only the number is relevant with this comparison
bool operator< ( const S& s ) const
{
return number < s.number;
}
};
struct Comp
{
bool operator() ( const S& s, int i )
{
return s.number < i;
}
bool operator() ( int i, const S& s )
{
return i < s.number;
}
};
int main()
{
std::vector<S> vec = { {1,'A'}, {2,'B'}, {2,'C'}, {2,'D'}, {3,'F'}, {4,'G'} }; //this syntax won't compile in VS2010, so you can leave an empty vector here
auto p = std::equal_range(vec.begin(),vec.end(),2,Comp());
for ( auto i = p.first; i != p.second; ++i )
std::cout << i->name << ' ';
}
This will compile fine in release mode, but in debug mode, it will fail to compile. The reason is that in debug mode, the implementation will check if the iterator range is already sorted, using the given predicate:
template<class _FwdIt,
class _Pr> inline
void _Debug_order2(_FwdIt _First, _FwdIt _Last, _Pr _Pred,
_Dbfile_t _File, _Dbline_t _Line, forward_iterator_tag)
{ // test if range is ordered by predicate, forward iterators
for (_FwdIt _Next = _First; _First != _Last && ++_Next != _Last; ++_First)
if (_DEBUG_LT_PRED(_Pred, *_Next, *_First))
_DEBUG_ERROR2("sequence not ordered", _File, _Line);
}
this ends up calling :
template<class _Pr, class _Ty1, class _Ty2> inline
bool _Debug_lt_pred(_Pr _Pred,
const _Ty1& _Left, const _Ty2& _Right,
_Dbfile_t _File, _Dbline_t _Line)
{ // test if _Pred(_Left, _Right) and _Pred is strict weak ordering
if (!_Pred(_Left, _Right))
return (false);
else if (_Pred(_Right, _Left))
_DEBUG_ERROR2("invalid operator<", _File, _Line);
return (true);
}
Except that in my case, no operator()
can take both left and right "S" argument.
So, is there a bug in the Visual implementation? Or is the original example not supposed to be portable?
I think I could make it work by providing a 3rd operator() overload, but it seems like it should work without
thanks
Nothing in the standard requires the comparator to be callable with two objects from the range. So that is a bug in the standard library used by VS 2010.
Here are all the relevant requirements (quoting C++11):
[lower.bound]§1+2:
1 Requires: The elements
e
of[first,last)
shall be partitioned with respect to the expression ...comp(e, value)
.2 Returns: The furthermost iterator
i
in the range[first,last]
such that for any iteratorj
in the range[first,i)
the following corresponding conditions hold: ...comp(*j, value) != false
.
[upper.bound]§1+2:
1 Requires: The elements
e
of[first,last)
shall be partitioned with respect to the expression ...!comp(value, e)
.2 Returns: The furthermost iterator
i
in the range[first,last]
such that for any iteratorj
in the range[first,i)
the following corresponding conditions hold: ...comp(value, *j) == false
.
[equal.range]§1+2:
1 Requires: The elements
e
of[first,last)
shall be partitioned with respect to the expressions ...comp(e, value)
and!comp(value, e)
. Also, for all elementse
of[first, last)
, ...comp(e, value)
shall imply!comp(value, e)
.2 Returns:
...
make_pair(lower_bound(first, last, value, comp), upper_bound(first, last, value, comp))
(The ellipses are for the non-comparator version).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With