<ranges>
エイリアスのテンプレート
エイリアス テンプレートは別の型のエイリアスであり、コードをより読みやすくすることができます。 たとえば、次のエイリアスconditional_t
は、渡されるrange
の種類に応じて、borrowed_range
またはdangling
範囲のエイリアスです。
// 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
}
エイリアス テンプレートの詳細については、「 Aliases と typedefsを参照してください。
<algorithm>
ヘッダーは、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 |
指定した範囲のセンチネルの種類を返します。 |
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
テストする範囲。
解説
右辺値範囲の有効期間は、範囲モデルが 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
右辺値range
引数を指定してsubrange
を返すアルゴリズム関数が呼び出されると、呼び出しの後で範囲の有効期間が終了する可能性があります。 つまり、返された 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
テストする範囲。
解説
右辺値範囲の有効期間は、範囲モデルが borrowed_range
かどうかに関係なく、関数呼び出しの後で終了できます。 borrowed_range
の場合、範囲の有効期間がいつ終了しても、適切に定義された動作で反復子を引き続き使用できる場合があります。
たとえば、コンテナーの有効期間が終了すると、反復子は破棄された要素を参照するため、 vector
や list
などのコンテナーでは、これが当てはまらない場合です。
たとえば、borrowed_range
の反復子を引き続き使用できます。たとえば、反復子がオンデマンドで生成されるために破棄されない値のセットを超えるiota_view<int>{0, 42}
などのview
に対して使用できます。
反復子が有効期間に依存する範囲にアルゴリズム関数が渡された場合、コンパイル時に誤用の可能性が検出されるように、サブ範囲の代わりに ranges::dangling
が返されます。
例: borrowed_subrange_t
次の例は、equal_range()
とmax_element
がこのテンプレート エイリアスを使用して戻り値の型を判断するため、borrowed_subrange_t
が未解決の反復子を検出する方法を示しています。
// 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
を返すアルゴリズム関数が右辺値 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
指定した範囲のセンチネルの種類を返します。
template <range R>
using sentinel_t = decltype(ranges::end(declval<R&>()));
パラメーター
R
Sentinel の種類を取得する範囲。
例: sentinel_t
次の例は、 sentinel_t
を使用して、反復子の型とセンチネルの型が同じかどうかを判断する方法を示しています。
// 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