在neighbor_find中使用Greater_equal在排序后的序列中查找等效元素

时间:2019-04-12 10:52:39

标签: c++ algorithm c++17 c++20

使用std::greater_equal算法中的std::adjacent_find来查找排序范围内的等效元素(与equal相反)是UB吗?

如果未严格指定算法实现内std::greater_equal<>{}(*prev, *next)中的 prev next 元素的顺序,则答案可能为“否”。

std::container<int> c{1, 2, 3, 3, 4, 5};
assert(std::is_sorted(std::cbegin(c), std::cend(c));
assert(std::adjacent_find(std::cbegin(c), std::cend(c), std::greater_equal<int>{}) != std::cend(c));

4 个答案:

答案 0 :(得分:3)

std::adjacent_find搜索两个连续的元素,其中谓词返回trueC++ standard将行为记录为发现:

  • *i == *(i + 1)用于无参数pred的重载
  • pred(*i, *(i + 1)) != false用于参数为pred的重载

第二个项目符号指定将元素传递给谓词的顺序。

此示例实现(copied from cppreference.com)应该使这一点更加清楚。

template<class ForwardIt, class BinaryPredicate>
ForwardIt adjacent_find(ForwardIt first, ForwardIt last, BinaryPredicate p)
{
    if (first == last) {
        return last;
    }
    ForwardIt next = first;
    ++next;
    for (; next != last; ++next, ++first) {
        if (p(*first, *next)) { // <- predicate called here
            return first;
        }
    }
    return last;
}

答案 1 :(得分:0)

  

在std :: adjacent_find算法中使用std :: less来查找是否是UB   在排序范围内是否等效(等于equal)?

这绝不是不确定的行为,传递给std::adjacent_find的谓词的唯一限制是正确的类型,而不能修改其参数。

答案 2 :(得分:0)

您正在查看此模板:

template< class ForwardIt, class BinaryPredicate>
ForwardIt adjacent_find( ForwardIt first, ForwardIt last, BinaryPredicate p );

p

  

p-二进制谓词,如果元素应被视为相等则返回true。

这里没有UB,只要满足算法要求即可。如果对于您的问题,您必须将less视为equal,则它是完全有效的。

答案 3 :(得分:0)

您没有UB,但是您不需要std::less,因为1 < 2会将迭代器返回到1

您需要:

std::vector<int> c{1, 2, 3, 3, 4, 5};
assert(std::is_sorted(std::cbegin(c), std::cend(c));
auto it = std::adjacent_find(std::cbegin(c), std::cend(c),
                             [](auto lhs, auto rhs){
                                 // For unsorted container, you would need
                                 // return !(lhs < rhs) && !(rhs < lhs);
                                 // but as container is sorted,
                                 // we already have (lhs < rhs) || !(rhs < lhs)
                                 return !(lhs < rhs);

                             });
// *it == 3; *(it+1) == 3;