Index: libcxx/trunk/include/algorithm =================================================================== --- libcxx/trunk/include/algorithm +++ libcxx/trunk/include/algorithm @@ -785,6 +785,15 @@ __debug_less(_Compare& __c) : __comp_(__c) {} template + bool operator()(const _Tp& __x, const _Up& __y) + { + bool __r = __comp_(__x, __y); + if (__r) + __do_compare_assert(0, __y, __x); + return __r; + } + + template _LIBCPP_CONSTEXPR_AFTER_CXX17 bool operator()(_Tp& __x, _Up& __y) { Index: libcxx/trunk/test/libcxx/algorithms/debug_less.pass.cpp =================================================================== --- libcxx/trunk/test/libcxx/algorithms/debug_less.pass.cpp +++ libcxx/trunk/test/libcxx/algorithms/debug_less.pass.cpp @@ -235,10 +235,45 @@ } } +struct ValueIterator { + using iterator_category = std::input_iterator_tag; + using value_type = size_t; + using difference_type = ptrdiff_t; + using reference = size_t; + using pointer = size_t*; + + ValueIterator() = default; + + reference operator*() { return 0; } + ValueIterator& operator++() { return *this; } + + friend bool operator==(ValueIterator, ValueIterator) { return true; } + friend bool operator!=(ValueIterator, ValueIterator) { return false; } +}; + +void test_value_iterator() { + // Ensure no build failures when iterators return values, not references. + assert(0 == std::lexicographical_compare(ValueIterator{}, ValueIterator{}, + ValueIterator{}, ValueIterator{})); +} + +void test_value_categories() { + std::less l; + std::__debug_less> dl(l); + int lvalue = 42; + const int const_lvalue = 101; + + assert(dl(lvalue, const_lvalue)); + assert(dl(/*rvalue*/1, lvalue)); + assert(dl(static_cast(1), static_cast(2))); +} + int main(int, char**) { test_passing(); test_failing(); test_upper_and_lower_bound(); test_non_const_arg_cmp(); + test_value_iterator(); + test_value_categories(); return 0; }