共用方式為


<ranges> 別名範本

別名範本是另一種類型的別名,可讓程式代碼更容易閱讀。 例如,下列別名 conditional_t是 或 dangling 範圍的別名borrowed_range,視傳入的range類型而定:

// requires /std:c++20, or later

#include <iostream>
#include <list>
#include <span>
#include <algorithm>
#include <ranges>
#include <type_traits>

using namespace std;

// Define an alias template called my_iterator_t
// If the provided range R is a borrowed_range, then the 
// returned type is iterator_t<R>; otherwise, ranges::dangling
template<ranges::range R>
using my_iterator_t = conditional_t<
    ranges::borrowed_range<R>,
    ranges::iterator_t<R>, ranges::dangling>;

int main()
{
    my_iterator_t<list<int>> aDanglingRange; // list<> isn't a borrowed_range
    constexpr bool same = same_as<
        decltype(aDanglingRange),
        ranges::dangling>; // true

    my_iterator_t<span<int, 5>> anIterator_t; // span<> is a borrowed_range
    constexpr bool same2 = same_as<
        decltype(anIterator_t),
        ranges::iterator_t<span<int, 5>>>; // true

    cout << boolalpha << same << "," << same2; // outputs true, true
}

如需別名範本的詳細資訊,請參閱 別名和 typedefs

標頭 <algorithm> 會定義下列別名範本,以判斷 的反覆運算器和 sentinels range類型:

別名範本 描述
borrowed_iterator_tC++20 判斷 傳回給 range 的反覆運算器是否是指其存留期已結束的範圍。
borrowed_subrange_tC++20 判斷 傳回給 range 的 是否subrange是指其存留期已結束的範圍。
danglingC++20 表示傳回的反覆運算器 range/subrange ,其存留期大於其所參考的 range/subrange 存留期。
iterator_tC++20 傳回指定範圍的反覆運算器類型。
range_difference_tC++20 傳回指定範圍反覆運算器的差異型別。
range_reference_tC++20 傳回指定範圍反覆運算器的參考型別。
range_rvalue_reference_tC++20 傳回指定範圍反覆運算器的右值參考型別。 換句話說,範圍元素的右值參考類型。
range_size_tC++20 傳回用來報告指定範圍的 size型別。
range_value_tC++20 傳回指定範圍反覆運算器的實值型別。 或者換句話說,範圍中的項目類型。
sentinel_tC++20 傳回指定範圍的 sentinel 類型。

borrowed_iterator_t

使用右值 range 自變數呼叫傳回反覆運算器的演算法函式時,範圍的存留期可能會在呼叫之後結束。 這表示傳回的反覆運算器可以參考已結束存留期的專案。 使用懸空反覆運算器會導致未定義的行為。

此範本別名會 ranges::dangling 傳回 ,表示這是指定範圍自變數的情況,或 std::ranges::iterator_t<R> 表示使用傳回的反覆運算器是安全的,因為參考模型 borrowed_range 的範圍或範圍是以左值傳遞。

template<ranges::range R>
using borrowed_iterator_t = conditional_t<ranges::borrowed_range<R>,
    ranges::iterator_t<R>, ranges::dangling>;

參數

R
要測試的範圍。

備註

rvalue 範圍的存留期可以結束於函數調用之後,不論範圍模型是否。borrowed_range borrowed_range如果是 ,則不論範圍的存留期何時結束,您都可以繼續使用具有妥善定義行為的反覆運算器。

例如,如果vectorlist容器的存留期結束,則反覆運算器會參考已終結的元素,例如,如果容器的存留期結束,則情況並非如此。

例如,您可以繼續使用 反覆運算器作為borrowed_range的反覆運算器,例如iota_view<int>{0, 42}view其反覆運算器超過一組值,這些值不受限於被終結,因為它們是隨選產生的。

如果演算法函式傳遞了反覆運算器相依於其存留期的範圍, ranges::dangling 則會傳回而不是反覆運算器或子範圍,因此在編譯時期偵測到潛在的誤用。

範例: borrowed_iterator_t

下列範例示範如何 borrowed_iterator_t 偵測懸空反覆運算器。 函式 ranges::max_element() 會使用此樣本別名來判斷傳回類型:

// requires /std:c++20, or later

#include <vector>
#include <span>
#include <ranges>
#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    // Not dangling ------------------

    int a[] = {0,1,2,3};

    // not dangling even though an rvalue because span models ranges::borrowed
    auto result1 = ranges::max_element(span{a});
    cout << boolalpha << ranges::borrowed_range<decltype(span{a})> << endl; // outputs true because the temporary models ranges::borrowed
    cout << same_as<decltype(result1), ranges::dangling> << endl; // outputs false because the result isn't dangling

    vector<int> v{0,1,2,3}; // doesn't model ranges::borrowed
    auto result2 = ranges::max_element(v); // Yet not dangling because passed as an lvalue
    cout << same_as<decltype(result2), ranges::dangling> << endl; // outputs false because the result isn't dangling
    
    // Dangling ------------------

    auto result3 = ranges::max_element(vector{0,1,2,3}); // dangling because vector doesn't model ranges::borrowed and is passed as an rvalue
    cout << same_as<decltype(result3), ranges::dangling>; // outputs true because the result is dangling
}
true
false
false
true

borrowed_subrange_t

當傳回 subrange 的演算法函式使用 rvalue range 自變數呼叫 時,範圍的存留期可能會在呼叫之後結束。 這表示傳回的 subrange 可以參考其存留期已結束的專案。 使用懸空 subrange 會導致未定義的行為。

此範本別名會傳回 ranges::dangling ,表示這可能是指定範圍自變數的情況,或 subrange<ranges::iterator_t<R>> 指出使用傳回的子範圍是安全的,因為其項目參考模型 borrowed_range 的範圍或範圍傳遞為左值。

template<ranges::range R>
using borrowed_subrange_t = conditional_t<ranges::borrowed_range<R>,
    ranges::subrange<ranges::iterator_t<R>>, ranges::dangling>;

參數

R
要測試的範圍。

備註

rvalue 範圍的存留期可以結束於函數調用之後,不論範圍模型是否。borrowed_range borrowed_range如果是 ,則不論範圍的存留期何時結束,您都可以繼續使用具有妥善定義行為的反覆運算器。

例如,如果vectorlist容器的存留期結束,則反覆運算器會參考已終結的元素,例如,如果容器的存留期結束,則情況並非如此。

例如,您可以繼續使用 反覆運算器作為borrowed_range的反覆運算器,例如iota_view<int>{0, 42}view其反覆運算器超過一組值,這些值不受限於被終結,因為它們是隨選產生的。

如果演算法函式傳遞了反覆運算器相依於其存留期的範圍,則會傳回 ,而不是子範圍, ranges::dangling 以便在編譯時期偵測到潛在的誤用。

範例: borrowed_subrange_t

下列範例示範如何 borrowed_subrange_t 偵測懸空反覆運算器,因為 equal_range()max_element 使用此範本別名來判斷傳回類型:

// requires /std:c++20, or later

#include <vector>
#include <iostream>
#include <algorithm>
#include <span>
#include <ranges>

int main()
{
    using namespace std;

    // Not dangling ------------------

    vector vec{0, 1, 1, 2};

    auto result1 = ranges::equal_range(span{vec}, 1); // not dangling even though passing as an rvalue because span models borrowed_range
    cout << boolalpha << ranges::borrowed_range<decltype(span{vec})> << endl;  // true because the temporary is a borrowed range
    cout << boolalpha << same_as<decltype(result1), ranges::dangling> << endl; // false because the result isn't dangling

    // result2 isn't dangling even though vec doesn't model ranges::borrowed because it's an lvalue
    auto result2 = ranges::max_element(vec);
    cout << boolalpha << ranges::borrowed_range<decltype(vec)> << endl;  // false because vector isn't a borrowed_range
    cout << boolalpha << same_as<decltype(result2), ranges::dangling> << endl; // false because the result isn't dangling

    // Dangling -----------------------

    // result3 is dangling because the temporary is an rvalue that doesn't model borrowed_range
    auto result3 = ranges::max_element(vector{0,1,1,2});
    cout << boolalpha << same_as<decltype(result3), ranges::dangling> << endl; // true because the result is dangling
}
true
false
false
false
true

dangling

如果傳回反覆運算器或 subrange 呼叫的演算法函式具有 rvalue range 自變數,範圍自變數的存留期可能會在呼叫之後結束。 這表示傳回的反覆運算器,或 subrange 可能參考已結束存留期的專案。 使用懸空反覆運算器或 subrange 導致未定義的行為。

如果演算法函式傳遞了反覆運算器相依於其存留期的範圍,則會傳回而不是反覆運算器或子範圍, ranges::dangling 以便在編譯時期偵測到潛在的誤用。

1) constexpr dangling() noexcept = default;
2) template<class... Args>
constexpr dangling(Args&&...) noexcept {}

參數

Args
void 型別的變數數目。 它們沒有作用。 自變數是一種便利性,因此您不需要不同的程式代碼路徑來處理建構反覆運算器類型與 dangling 類型。 當傳入的值指出 dangling 應該傳回而不是反覆運算器時,這會很有用。

範例: dangling

下列範例示範如何 max_element 偵測懸空反覆運算器。

// requires /std:c++20, or later

#include <vector>
#include <iostream>
#include <ranges>
#include <algorithm>

using namespace std;

int main()
{
    auto result1 = ranges::max_element(vector{1,2,3}); // dangling because vector doesn't model ranges::borrowed and is passed as an rvalue
    cout << boolalpha << same_as<decltype(result1), ranges::dangling> << endl; // outputs true because the result is dangling

    vector<int> v{3,4,5};
    auto result2 = ranges::max_element(v); // Not dangling because passed as an lvalue
    cout << same_as<decltype(result2), ranges::dangling>; // outputs false because the result isn't dangling
}
true
false

iterator_t

此範本別名會傳回反覆運算器類型,用來逐一查看提供的範圍類型。

template<class T>
using iterator_t = decltype(ranges::begin(declval<T&>()));

參數

T
要為其取得反覆運算器類型的範圍類型。

範例: iterator_t

下列範例示範如何使用 來 iterator_t 宣告向量的反覆運算器:

// requires /std:c++20, or later

#include <vector>
#include <ranges>
#include <iostream>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};

    ranges::iterator_t<decltype(v)> it = v.begin();
    cout << *it << "\n"; // outputs 1
    cout << typeid(it).name(); // outputs class _Vector_iterator<class _Vector_val<struct _Simple_types<int>>>
}
1
class std::_Vector_iterator<class std::_Vector_val<struct std::_Simple_types<int> > >

range_difference_t

傳回指定範圍反覆運算器的差異型別。

template<range R>
using range_difference_t = iter_difference_t<iterator_t<R>>;

參數

R
反覆運算器將提供差異型別的範圍。

範例: range_difference_t

下列範例示範如何使用 range_difference_t 來保存範圍中專案之間的距離:

// requires /std:c++20, or later

#include <vector>
#include <ranges>
#include <iostream>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};

    auto findIt = ranges::find(v, 2);
    // type of distance is ptrdiff_t
    ranges::range_difference_t<decltype(v)> distance = ranges::distance(v.begin(), findIt);
    cout << distance << endl; // outputs 1
}
1

range_reference_t

傳回指定範圍反覆運算器的參考型別。 換句話說,範圍項目的參考型別。

template <range R>
using range_reference_t = iter_reference_t<ranges::iterator_t<R>>;

參數

R
傳回其反覆運算器型別之參考型別的範圍。

範例: range_reference_t

下列範例顯示 range_reference_t 參考範圍中的項目類型:

// requires /std:c++20, or later

#include <vector>
#include <ranges>
#include <iostream>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};

    ranges::range_reference_t<decltype(v)> ref = v[0];

    cout << ref << endl; // outputs 1
    cout << typeid(ref).name() << endl; // outputs int
}
1
int

range_rvalue_reference_t

傳回指定範圍反覆運算器的右值參考型別。 換句話說,範圍元素的右值參考類型。

template <range R>
using range_rvalue_reference_t = iter_reference_t<ranges::iterator_t<R>>;

參數

R
要為其反覆運算器型別取得右值參考型別的範圍。

範例: range_rvalue_reference_t

下列範例顯示 range_rvalue_reference_t 參考範圍中元素的右值類型:

// requires /std:c++20, or later

#include <vector>
#include <ranges>
#include <iostream>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};

    ranges::range_rvalue_reference_t<decltype(v)> elementRvalueType = v[0] * 10; // elementRvalueType is int&& 

    cout << elementRvalueType << endl; // outputs 10
    cout << typeid(elementRvalueType).name() << endl; // outputs int
}
10
int

range_size_t

傳回指定 sized_range之函size式的類型。

template <range R>
using range_size_t = iter_reference_t<ranges::iterator_t<R>>;

參數

R
要取得其 size 函式類型的範圍。

範例: range_size_t

下列範例顯示 range_size_t 參考範圍中的項目數目:

// requires /std:c++20, or later

#include <vector>
#include <iostream>
#include <ranges>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};

    ranges::range_size_t<decltype(v)> size = v.size();
    cout << size << endl; // outputs 3
    cout << typeid(size).name(); // outputs unsigned __int64
}
3
unsigned __int64

range_value_t

傳回指定範圍反覆運算器的實值型別。 或者換句話說,範圍中的項目類型。

template <ranges::range R>
using range_value_t = iter_value_t<ranges::iterator_t<R>>;

參數

R
要取得其反覆運算器之實值型別的範圍。

範例: range_value_t

下列範例示範如何 range_value_t 參考範圍中的項目類型:

// requires /std:c++20, or later

#include <vector>
#include <ranges>
#include <iostream>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};
    ranges::range_value_t<decltype(v)> elementType = v[2]; // elementType is an int 

    cout << elementType << endl; // outputs 3
    cout << typeid(elementType).name() << endl; // outputs int
}
3
unsigned int

sentinel_t

傳回指定範圍的 sentinel 類型。

template <range R>
using sentinel_t = decltype(ranges::end(declval<R&>()));

參數

R
要為其取得 sentinel 型別的範圍。

範例: sentinel_t

下列範例示範如何使用 sentinel_t 來判斷反覆運算器類型和 sentinel 類型是否相同:

// requires /std:c++20, or later

#include <iostream>
#include <list>
#include <ranges>

int main()
{
    using namespace std;

    list myList{1, 2, 3};
    ranges::subrange count = std::views::counted(myList.begin(), myList.size());

    ranges::iterator_t<decltype(count)> first;
    ranges::sentinel_t<decltype(count)> last;

    // The iterator type and the sentinel type of a subrange
    // obtained from views::counted are not the same
    cout << boolalpha << is_same<decltype(first), decltype(last)>::value << endl; // outputs false
    cout << "iter: " << typeid(first).name() << "\n\n end: " << typeid(last).name() << endl;
}
false
iter: class std::counted_iterator<class std::_List_iterator<class std::_List_val<struct std::_List_simple_types<int> > > >

 end: struct std::default_sentinel_t

另請參閱

<ranges>
範圍配接器
檢視類別