# std::ranges::views::filter, std::ranges::filter_view

< cpp‎ | ranges

定义于头文件 `<ranges>` |  |
template< ranges::input_range V, std::indirect_unary_predicate<ranges::iterator_t<V>> Pred > requires ranges::view<V> && std::is_object_v<Pred> class filter_view : public ranges::view_interface<filter_view<V, Pred>> | (1) | (C++20 起)
namespace views { inline constexpr /*unspecified*/ filter = /*unspecified*/; } | (2) | (C++20 起)

1) 表示排除了不能满足谓词的元素的底层序列的 `view` 的范围适配器。
2) 范围适配器对象。对任何适合的子表达式 e 与 p ，表达式 views::filter(e, p) 表达式等价于 filter_view(e, p) 。

`filter_view` 在底层 `view` `V` 实现 `bidirectional_range`、 `forward_range`、 `input_range` 及 `common_range` 时分别实现相应的概念。

### 表达式等价

表达式 e 表达式等价于表达式 f ，若 e 与 f 拥有相同效果，均为潜在抛出或均非潜在抛出（即 noexcept(e) == noexcept(f) ），且均为常量子表达式或均非常量子表达式。

### 数据成员

`filter_view` 的典型实现保有二或三个数据成员：

- `V` 类型的底层 `view` （此处示为 `base_` ，仅为阐释），
- /*copyable-box*/<Pred> 类型的包装，包装用于滤出 `base_` 的元素的谓词（此处示为 `pred_` ，仅为阐释），其中 `copyable-box` 时始终满足 `copyable` 的包装类模板，
- std::optional 式对象（此处示为 `begin_` ，仅为阐释），缓存指向 `base_` 的首个满足 `pred_` 的元素的迭代器。 `begin_` 可能仅若 `filter_view` 实现 `forward_range` 才存在。

### 成员函数

(构造函数) (C++20) | 构造 `filter_view` (公开成员函数)
base (C++20) | 返回底层视图 `V` (公开成员函数)
pred (C++20) | 返回到存储于 `filter_view` 内的谓词的引用 (公开成员函数)
begin (C++20) | 返回 `filter_view` 的起始迭代器 (公开成员函数)
end (C++20) | 返回 `filter_view` 的哨位 (公开成员函数)
##### 继承自 std::ranges::view_interface
empty (C++20) | 返回视图是否为空。若视图满足 `forward_range` 则提供。 (`std::ranges::view_interface<D>` 的公开成员函数)
operator bool (C++20) | 返回派生视图是否为非空。若 ranges::empty 可应用于它则提供。 (`std::ranges::view_interface<D>` 的公开成员函数)
front (C++20) | 返回派生视图中的首元素。若视图满足 `forward_range` 则提供。 (`std::ranges::view_interface<D>` 的公开成员函数)
back (C++20) | 返回派生视图中的末元素。若视图满足 `bidirectional_range` 与 `common_range` 则提供。 (`std::ranges::view_interface<D>` 的公开成员函数)

## std::ranges::filter_view::filter_view

filter_view() requires std::default_initializable<V> && std::default_initializable<Pred> = default; | (1) | (C++20 起)
constexpr filter_view( V base, Pred pred ); | (2) | (C++20 起)

1) 经由其默认成员初始化器（= V()）值初始化 `base_` 并默认初始化 `pred_` （这值初始化其所含的 `Pred` ）。
2) 以 std::move(base) 初始化 `base_` 并以 std::move(pred) 初始化 `pred_` 。

### 参数

base | - | 要滤的范围
pred | - | 滤出元素的谓词

## std::ranges::filter_view::base

constexpr V base() const& requires std::copy_constructible<V>; | (1) | (C++20 起)
constexpr V base() &&; | (2) | (C++20 起)

1) 等价于 return base_; 。
2) 等价于 return std::move(base_); 。

## std::ranges::filter_view::pred

constexpr const Pred& pred() const; |  | (C++20 起)

返回到存储的 `Pred` 对象的引用。若 `pred_` 不含值则行为未定义。

## std::ranges::filter_view::begin

constexpr /*iterator*/ begin(); |  | (C++20 起)

为提供 `range` 概念所要求的均摊常数时间复杂度，此函数在 `filter_view` 对象内存储结果以用于后继调用。等价于

    if constexpr (!ranges::forward_range<V>) {
        return /*iterator*/{*this, ranges::find_if(base_, std::ref(*pred_))};
    } else {
        if (!begin_.has_value())
            begin_ = ranges::find_if(base_, std::ref(*pred_)); // 缓存
        return /*iterator*/{*this, begin_.value())};
    }

若 `pred_` 不含值则行为未定义。

## std::ranges::filter_view::end

constexpr auto end() { if constexpr (ranges::common_range<V>) return /*iterator*/{*this, ranges::end(base_)}; else return /*sentinel*/{*this}; } |  | (C++20 起)

### 推导指引

template< class R, class Pred > filter_view( R&&, Pred ) -> filter_view<views::all_t<R>, Pred>; |  | (C++20 起)

### 嵌套类

iterator (C++20) | `filter_view` 的迭代器类型 (仅用于阐释的成员类)
sentinel (C++20) | 底层视图非 `common_range` 时的 `filter_view` 的哨位类型 (仅用于阐释的成员类)

### 示例

    #include <iostream>
    #include <ranges>

    int main() {
        auto even = [](int i) { return 0 == i % 2; };
        auto square = [](int i) { return i * i; };

        for (int i : std::views::iota(0, 6)
                   | std::views::filter(even)
                   | std::views::transform(square)) {
            std::cout << i << ' ';
        }
    }

输出：

    0 4 16

### 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

DR | 应用于 | 出版时的行为 | 正确行为
--- | --- | --- | ---
P2325R3 | C++20 | 若 `Pred` 非 `default_initializable` ， 则默认构造函数构造不含 `Pred` 的 `filter_view` | `filter_view` 亦非 `default_initializable`

### 参阅

ranges::take_while_view views::take_while (C++20) | 由另一 `view` 的到首个谓词返回 `false` 为止的起始元素组成的 `view` (类模板) (范围适配器对象)