C++ 具名要求-全库范围的概念 -谓词(Predicate)-二元谓词(BinaryPredicate)

发布时间:2024年01月11日

此页面中列出的具名要求,是 C++ 标准的规范性文本中使用的具名要求,用于定义标准库的期待。

某些具名要求在 C++20 中正在以概念语言特性进行形式化。在那之前,确保以满足这些要求的模板实参实例化标准库模板是程序员的重担。若不这么做,则可能导致非常复杂的编译器诊断。

全库范围的概念

谓词

函数对象 (FunctionObject) ,对于一个实参,返回一个可转换为 bool 的值而不改动实参
C++ 具名要求: Predicate

谓词 (Predicate) 要求描述了返回可作为 bool 测试的值的可调用 (Callable) 体。

谓词 (Predicate) 常与接收输入数据(单独的对象/容器)和谓词的算法一起使用,它会针对输入数据进行调用以决定进一步的动作。C++ 标准库中的一些使用谓词的例子有:

  • std::all_of、std::any_of、std::none_of 接收一组元素和一个谓词为其输入。在每个单独的输入元素上调用谓词,并且当谓词分别对全部/任一/无元素返回 true 时返回 true。
  • std::find_if 接受元素的序列和一个谓词。返回序列中首个谓词对其返回 true 的元素。

上面给出的算法设施描述是简陋的,并且有意地简要解释谓词 (Predicate) 。对于详细信息可查阅各自的页面。

换言之,若算法接收一个谓词 (Predicate) pred 和一个迭代器 first,则它应该能经由类似 if(pred(*first)) {...} 的构造,测试迭代器 first 所指向的类型。

函数对象 pred 不应当通过解引用的迭代器运用任何非 const 函数。此函数对象可以是函数指针,或者拥有适合的函数调用运算符的类型的对象。

二元谓词

函数对象 (FunctionObject) ,对于两个实参,返回一个可转换为 bool 的值而不改动各实参
C++ 具名要求: BinaryPredicate

二元谓词 (BinaryPredicate) 是一些标准库设施针对用户提供的实参所期待的一组要求。

给定二元谓词 (BinaryPredicate) bin_pred 和一对迭代器 iter1iter2 或一个迭代器 iter 与值 value,表达式 bin_pred(*iter1, *iter2) 或 bin_pred(*iter, value) 必须可按语境转换为 bool。

另外,不允许表达式的求值调用解引用迭代器的非 const 成员函数。

要求

  • 谓词 (Predicate)
  • 可复制构造 (CopyConstructible) (除非另行指明)

标准库

下列标准库设施期待并非比较 (Compare) 类型的二元谓词 (BinaryPredicate)

unique

删除连续的重复元素
(std::forward_list<T,Allocator> 的公开成员函数)

unique

删除连续的重复元素
(std::list<T,Allocator> 的公开成员函数)

find_end

在特定范围中寻找最后出现的元素序列
(函数模板)

find_first_of

搜索元素集合中的任意元素
(函数模板)

adjacent_find

查找首对相邻的相同(或满足给定谓词的)元素
(函数模板)

mismatch

寻找两个范围出现不同的首个位置
(函数模板)

equal

确定两个元素集合是否是相同的
(函数模板)

is_permutation

(C++11)

判断一个序列是否为另一个序列的排列
(函数模板)

search

搜索一个元素范围
(函数模板)

search_n

在范围中搜索一定量的某个元素的连续副本
(函数模板)

unique

移除范围内的连续重复元素
(函数模板)

unique_copy

创建某范围的不含连续重复元素的副本
(函数模板)

not2

(C++17 中弃用)(C++20 中移除)

构造定制的 std::binary_negate 对象
(函数模板)

unordered_set

(C++11 起)

唯一键的集合,按照键生成散列
(类模板)

unordered_map

(C++11 起)

键值对的集合,按照键生成散列,键是唯一的
(类模板)

unordered_multiset

(C++11 起)

键的集合,按照键生成散列
(类模板)

unordered_multimap

(C++11 起)

键值对的集合,按照键生成散列
(类模板)

调用示例

?

#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
#include <functional>
#include <time.h>
#include <vector>

struct Cell
{
    int x;
    int y;

    Cell() = default;
    Cell(int a, int b): x(a), y(b) {}

    Cell &operator +=(const Cell &cell)
    {
        x += cell.x;
        y += cell.y;
        return *this;
    }

    Cell &operator +(const Cell &cell)
    {
        x += cell.x;
        y += cell.y;
        return *this;
    }

    Cell &operator *(const Cell &cell)
    {
        x *= cell.x;
        y *= cell.y;
        return *this;
    }

    Cell &operator ++()
    {
        x += 1;
        y += 1;
        return *this;
    }


    bool operator <(const Cell &cell) const
    {
        if (x == cell.x)
        {
            return y < cell.y;
        }
        else
        {
            return x < cell.x;
        }
    }

    bool operator >(const Cell &cell) const
    {
        if (x == cell.x)
        {
            return y > cell.y;
        }
        else
        {
            return x > cell.x;
        }
    }

    bool operator ==(const Cell &cell) const
    {
        return x == cell.x && y == cell.y;
    }
};

std::ostream &operator<<(std::ostream &os, const Cell &cell)
{
    os << "{" << cell.x << "," << cell.y << "}";
    return os;
}


int main()
{
    std::cout << std::boolalpha;

    std::vector<Cell> vector1{{101, 102}, {103, 104}, {105, 106}, {107, 108}};

    auto function1 = [](const Cell & cell)
    {
        if (cell > Cell{105, 106})
        {
            return true;
        }

        return false;
    };

    std::cout << "std::all_of(  > Cell{105, 106}):    "
              << std::all_of(vector1.begin(), vector1.end(), function1) << std::endl;

    std::cout << "std::any_of(  > Cell{105, 106}):    "
              << std::any_of(vector1.begin(), vector1.end(), function1) << std::endl;

    std::cout << "std::none_of( > Cell{105, 106}):    "
              << std::none_of(vector1.begin(), vector1.end(), function1) << std::endl;
    std::cout << std::endl;

    auto function2 = [](const Cell & cell1, const Cell & cell2)
    {
        return cell1 == cell2;
    } ;
    std::vector<Cell> vector2 = vector1;
    vector2.push_back({107, 108});
    std::copy(vector2.cbegin(), vector2.cend(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    std::unique(vector2.begin(), vector2.end(), function2);
    std::cout << "after unique:" << std::endl;
    std::copy(vector2.cbegin(), vector2.cend(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;

    std::cout << "std::equal(vector1.begin(), vector1.end(), vector2.begin(), function2):   "
              << std::equal(vector1.begin(), vector1.end(), vector2.begin(), function2);
    return 0;
}

输出

std::all_of(  > Cell{105, 106}):    false
std::any_of(  > Cell{105, 106}):    true
std::none_of( > Cell{105, 106}):    false

{101,102} {103,104} {105,106} {107,108} {107,108}
after unique:
{101,102} {103,104} {105,106} {107,108} {107,108}
std::equal(vector1.begin(), vector1.end(), vector2.begin(), function2):   true

文章来源:https://blog.csdn.net/qq_40788199/article/details/135515684
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。