std::ranges::views::common,?std::ranges::common_view
C++20 引入的用于將范圍適配為“通用范圍”的工具,主要解決某些算法需要傳統迭代器對(如?begin
?和?end
?類型相同)的問題。
基本概念
1.?功能
- 適配傳統算法:將范圍(range)的迭代器和哨兵(sentinel)類型統一,使其適配需要“迭代器對”的舊式算法(如 C++17 之前的算法)。
- 類型一致性:確保?
begin()
?和?end()
?返回的迭代器類型相同。 - 零開銷原則:僅在必要時添加類型轉換,無額外內存分配。
以下是詳細說明和示例:
核心概念
- 問題背景:C++20 的某些范圍(如?
split_view
)的?begin
?和?end
?返回的迭代器類型可能不同,但傳統算法(如 C++17 前的算法)需要它們類型相同。 - 解決方案:
common_view
?將范圍適配為?begin
?和?end
?迭代器類型相同的“通用范圍”。
std::ranges::common_view
- 定義:
template<std::ranges::view V> class common_view : public std::ranges::view_interface<common_view<V>>
- 適用場景:
- 當原始范圍的迭代器和哨兵類型不同,但需要轉換為相同類型時。
- 需要將范圍傳遞給傳統算法(如接受?
int*
?和?int*
?的算法)。
語法與參數
1. 語法
auto common_view = range | std::ranges::views::common;
range
:輸入范圍(如容器、視圖)。
示例 1:適配?split_view
#include <ranges>
#include <vector>
#include <algorithm>
#include <iostream>int main() {std::string str = "hello,world,cpp20";auto split = str | std::views::split(',');// split 的迭代器和哨兵類型不同,無法直接傳遞給傳統算法// 使用 common_view 適配auto common_range = split | std::views::common;// 現在可以像傳統范圍一樣使用for (const auto& part : common_range) {for (char c : part) std::cout << c;std::cout << '\n';}
}
示例 2:傳遞給傳統算法
某些傳統算法(如?std::sort
)要求?begin()
?和?end()
?的迭代器類型嚴格一致,但 C++20 的某些范圍(如?std::ranges::iota_view
)可能返回不同類型的哨兵:
示例 2:處理子范圍
#include <ranges>
#include <vector>
#include <algorithm>
#include <iostream>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};auto reversed = vec | std::views::reverse;// 傳統算法需要 begin 和 end 類型相同// 使用 common_view 適配auto common_reversed = reversed | std::views::common;// 使用 std::sort(僅示例,反轉后排序可能無意義)std::ranges::sort(common_reversed); // 需要迭代器類型相同for (int x : common_reversed) {std::cout << x << ' '; // 輸出:1 2 3 4 5(排序后的反轉)}
}
std::ranges::views::common
- 定義:范圍適配器對象,可通過管道操作符?
|
?簡化?common_view
?的創建。 - 等效操作:
views::common(r)
?等價于?common_view<views::all_t<decltype(r)>>{r}
。
示例 3:結合管道操作符
#include <ranges>
#include <iostream>
#include <list>
#include <algorithm> // 必須包含此頭文件以使用 std::findint main() {std::list<int> lst = {1, 2, 3, 4, 5};auto even = lst | std::views::filter([](int x) { return x % 2 == 0; });// 使用 views::common 適配auto common_even = even | std::views::common;// 傳遞給傳統算法 std::findif (std::find(common_even.begin(), common_even.end(), 4) != common_even.end()) {std::cout << "Found 4\n";}
}
注意事項
- 性能:
common_view
?可能引入額外開銷(如緩存迭代器),需謹慎使用。 - 適用性:僅在需要傳統迭代器對時使用,現代算法(如?
std::ranges::sort
)通常不需要。 - 生命周期:確保底層范圍的生命周期長于?
common_view
。
總結
common_view
:將?begin
?和?end
?迭代器類型不同的范圍適配為類型相同的通用范圍。views::common
:通過管道操作符簡化?common_view
?的創建。- 典型場景:與傳統算法交互,或需要迭代器類型一致的操作。