_ForwardIterator
lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp)
{
-#ifdef _LIBCPP_DEBUG
- typedef typename add_lvalue_reference<__debug_less<_Compare> >::type _Comp_ref;
- __debug_less<_Compare> __c(__comp);
- return __lower_bound<_Comp_ref>(__first, __last, __value_, __c);
-#else // _LIBCPP_DEBUG
typedef typename add_lvalue_reference<_Compare>::type _Comp_ref;
return __lower_bound<_Comp_ref>(__first, __last, __value_, __comp);
-#endif // _LIBCPP_DEBUG
}
template <class _ForwardIterator, class _Tp>
_ForwardIterator
upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp)
{
-#ifdef _LIBCPP_DEBUG
- typedef typename add_lvalue_reference<__debug_less<_Compare> >::type _Comp_ref;
- __debug_less<_Compare> __c(__comp);
- return __upper_bound<_Comp_ref>(__first, __last, __value_, __c);
-#else // _LIBCPP_DEBUG
typedef typename add_lvalue_reference<_Compare>::type _Comp_ref;
return __upper_bound<_Comp_ref>(__first, __last, __value_, __comp);
-#endif // _LIBCPP_DEBUG
}
template <class _ForwardIterator, class _Tp>
}
}
+template <int>
+struct Tag {
+ explicit Tag(int v) : value(v) {}
+ int value;
+};
+
+template <class = void>
+struct FooImp {
+ explicit FooImp(int x) : x_(x) {}
+ int x_;
+};
+
+template <class T>
+inline bool operator<(FooImp<T> const& x, Tag<0> y) {
+ return x.x_ < y.value;
+}
+
+template <class T>
+inline bool operator<(Tag<0>, FooImp<T> const&) {
+ static_assert(sizeof(FooImp<T>) != sizeof(FooImp<T>), "should not be instantiated");
+}
+
+template <class T>
+inline bool operator<(Tag<1> x, FooImp<T> const& y) {
+ return x.value < y.x_;
+}
+
+template <class T>
+inline bool operator<(FooImp<T> const&, Tag<1>) {
+ static_assert(sizeof(FooImp<T>) != sizeof(FooImp<T>), "should not be instantiated");
+}
+
+typedef FooImp<> Foo;
+
+// Test that we don't attempt to call the comparator with the arguments reversed
+// for upper_bound and lower_bound since the comparator or type is not required
+// to support it, nor does it require the range to have a strict weak ordering.
+// See llvm.org/PR39458
+void test_upper_and_lower_bound() {
+ Foo table[] = {Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)};
+ {
+ Foo* iter = std::lower_bound(std::begin(table), std::end(table), Tag<0>(3));
+ assert(iter == (table + 2));
+ }
+ {
+ Foo* iter = std::upper_bound(std::begin(table), std::end(table), Tag<1>(3));
+ assert(iter == (table + 3));
+ }
+}
+
int main() {
test_passing();
test_failing();
+ test_upper_and_lower_bound();
}