std::ranges::shift_left, std::ranges::shift_right

出自cppreference.com
< cpp‎ | algorithm‎ | ranges
在2025年2月13日 (四) 00:37由YexuanXiao對話 | 貢獻所做的修訂版本

(差異) ←上一修訂 | 最新修訂 (差異) | 下一修訂→ (差異)
 
 
算法庫
受約束算法及範圍上的算法 (C++20)
包含算法例如 ranges::copy, ranges::sort, ...
執行策略 (C++17)
排序和相關操作
劃分操作
排序操作
二分搜索操作(在已劃分範圍上)
集合操作(在有序範圍上)
歸併操作(在有序範圍上)
堆操作
最小/最大操作
(C++11)
(C++17)
字典序比較操作
排列操作
C 庫

數值運算
(C++11)                       
在未初始化內存上的操作
 
受約束算法
本菜單中的所有名字均屬於命名空間 std::ranges
不修改序列的操作
修改序列的操作
劃分操作
排序操作
二分搜索操作(在有序範圍上)
       
       
集合操作(在有序範圍上)
堆操作
最小/最大操作
       
       
排列操作
摺疊操作
數值操作
(C++23)            
未初始化存儲上的操作
返回類型
 
在標頭 <algorithm> 定義
調用簽名
template< std::permutable I, std::sentinel_for<I> S >

constexpr ranges::subrange<I>

    shift_left( I first, S last, std::iter_difference_t<I> n );
(1) (C++23 起)
template< ranges::forward_range R >

requires std::permutable<ranges::iterator_t<R>>
constexpr ranges::borrowed_subrange_t<R>

    shift_left( R&& r, ranges::range_difference_t<R> n );
(2) (C++23 起)
template< std::permutable I, std::sentinel_for<I> S >

constexpr ranges::subrange<I>

    shift_right( I first, S last, std::iter_difference_t<I> n );
(3) (C++23 起)
template< ranges::forward_range R >

requires std::permutable<ranges::iterator_t<R>>
constexpr ranges::borrowed_subrange_t<R>

    shift_right( R&& r, ranges::range_difference_t<R> n );
(4) (C++23 起)

將範圍 [firstlast)r 中的各元素遷移 n 個位置。若 [firstlast) 不是有效範圍則其行為未定義。

1) 向範圍開端遷移元素:
  • n == 0 || n >= last - first 則無效果。
  • n < 0 則行為未定義。
  • 否則,對於每個 [0last - first - n) 中的整數 i,移動原處於位置 first + n + i 的元素到位置 first + i。以 i0 開始遞增的順序進行移動。
3) 向範圍結尾遷移元素:
  • n == 0 || n >= last - first 則無效果。
  • n < 0 則行為未定義。
  • 否則,對於每個 [0last - first - n) 中的整數 i,移動原處於位置 first + i 的元素到位置 first + n + i。若 I 滿足 bidirectional_iterator,則以 ilast - first - n - 1 開始遞減的順序進行移動。
2,4) 分別同 (1)(3),但以 r 為範圍,如同以 ranges::begin(r)first 並以 ranges::end(r)last

在原範圍但不在新範圍中的元素被置於合法但未指定的狀態。

此頁面上描述的函數式實體是算法函數對象(非正式地稱為 niebloid),即:

目錄

[編輯] 參數

first, last - 要遷移的元素範圍的迭代器-哨位對
r - 要遷移的元素範圍
n - 要遷移的位置數

[編輯] 返回值

1,2) {first, /*NEW_LAST*/},其中 NEW_LAST 為結果範圍的結尾:
  • n 小於 last - first,則等價於 first + (last - first - n)
  • 否則等價於 first
3,4) {/*NEW_FIRST*/, last},其中 NEW_FIRST 為結果範圍的開始:
  • n 小於 last - first,則等價於 first + n
  • 否則等價於 last

[編輯] 複雜度

1,2) 最多賦值 ranges::distance(first, last) - n 次。
3,4) 最多賦值或交換 ranges::distance(first, last) - n 次。

[編輯] 註解

常見實現上,若 I 滿足 bidirectional_iterator 或(更好地)random_access_iterator,則 ranges::shift_left / ranges::shift_right 會有更好的性能。

實現(例如 MSVC STL )可能在迭代器類型實現 contiguous_iterator ,並且交換其值類型不調用非平凡的特殊成員函數或 ADL 所找到的 swap 時啟用向量化。

功能特性測試 標準 功能特性
__cpp_lib_shift 202202L (C++23) std::ranges::shift_leftstd::ranges::shift_right

[編輯] 示例

#include <algorithm>
#include <iostream>
#include <string>
#include <type_traits>
#include <vector>
 
struct S
{
    int value{0};
    bool specified_state{true};
 
    S(int v = 0) : value{v} {}
    S(S const& rhs) = default;
    S(S&& rhs) { *this = std::move(rhs); }
    S& operator=(S const& rhs) = default;
    S& operator=(S&& rhs)
    {
        if (this != &rhs)
        {
            value = rhs.value;
            specified_state = rhs.specified_state;
            rhs.specified_state = false;
        }
        return *this;
    }
};
 
template<typename T>
std::ostream& operator<<(std::ostream& os, std::vector<T> const& v)
{
    for (const auto& s : v)
    {
        if constexpr (std::is_same_v<T, S>)
            s.specified_state ? os << s.value << ' ' : os << ". ";
        else if constexpr (std::is_same_v<T, std::string>)
            os << (s.empty() ? "." : s) << ' ';
        else
            os << s << ' ';
    }
    return os;
}
 
int main()
{
    std::cout << std::left;
 
    std::vector<S> a{1, 2, 3, 4, 5, 6, 7};
    std::vector<int> b{1, 2, 3, 4, 5, 6, 7};
    std::vector<std::string> c{"α", "β", "γ", "δ", "ε", "ζ", "η"};
 
    std::cout << "vector<S> \tvector<int> \tvector<string>\n";
    std::cout << a << "  " << b << "  " << c << '\n';
 
    std::ranges::shift_left(a, 3);
    std::ranges::shift_left(b, 3);
    std::ranges::shift_left(c, 3);
    std::cout << a << "  " << b << "  " << c << '\n';
 
    std::ranges::shift_right(a, 2);
    std::ranges::shift_right(b, 2);
    std::ranges::shift_right(c, 2);
    std::cout << a << "  " << b << "  " << c << '\n';
 
    std::ranges::shift_left(a, 8); // 无效果: n >= last - first
    std::ranges::shift_left(b, 8); // 同上
    std::ranges::shift_left(c, 8); // 同上
    std::cout << a << "  " << b << "  " << c << '\n';
 
//  std::ranges::shift_left(a, -3); // UB
}

可能的輸出:

vector<S>       vector<int>     vector<string>
1 2 3 4 5 6 7   1 2 3 4 5 6 7   α β γ δ ε ζ η
4 5 6 7 . . .   4 5 6 7 5 6 7   δ ε ζ η . . .
. . 4 5 6 7 .   4 5 4 5 6 7 5   . . δ ε ζ η .
. . 4 5 6 7 .   4 5 4 5 6 7 5   . . δ ε ζ η .

[編輯] 參閱

將範圍中元素移到新位置
(算法函數對象) [編輯]
從後往前將範圍中元素移到新位置
(算法函數對象) [編輯]
旋轉範圍中的元素順序
(算法函數對象) [編輯]
遷移範圍中元素
(函數模板) [編輯]