<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_t C++20 |
判斷 傳回給 range 的反覆運算器是否是指其存留期已結束的範圍。 |
borrowed_subrange_t C++20 |
判斷 傳回給 range 的 是否subrange 是指其存留期已結束的範圍。 |
dangling C++20 |
表示傳回的反覆運算器 range /subrange ,其存留期大於其所參考的 range /subrange 存留期。 |
iterator_t C++20 |
傳回指定範圍的反覆運算器類型。 |
range_difference_t C++20 |
傳回指定範圍反覆運算器的差異型別。 |
range_reference_t C++20 |
傳回指定範圍反覆運算器的參考型別。 |
range_rvalue_reference_t C++20 |
傳回指定範圍反覆運算器的右值參考型別。 換句話說,範圍元素的右值參考類型。 |
range_size_t C++20 |
傳回用來報告指定範圍的 size 型別。 |
range_value_t C++20 |
傳回指定範圍反覆運算器的實值型別。 或者換句話說,範圍中的項目類型。 |
sentinel_t C++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
如果是 ,則不論範圍的存留期何時結束,您都可以繼續使用具有妥善定義行為的反覆運算器。
例如,如果vector
list
容器的存留期結束,則反覆運算器會參考已終結的元素,例如,如果容器的存留期結束,則情況並非如此。
例如,您可以繼續使用 反覆運算器作為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
如果是 ,則不論範圍的存留期何時結束,您都可以繼續使用具有妥善定義行為的反覆運算器。
例如,如果vector
list
容器的存留期結束,則反覆運算器會參考已終結的元素,例如,如果容器的存留期結束,則情況並非如此。
例如,您可以繼續使用 反覆運算器作為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