namespace std::ranges {
template<class T>
concept viewable_range =
range<T> &&
((view<remove_cvref_t<T>> && constructible_from<remove_cvref_t<T>, T>) ||
(!view<remove_cvref_t<T>> &&
(is_lvalue_reference_v<T> || (movable<remove_reference_t<T>> && !is-initializer-list<T>))));
}
概要
viewable_rangeは、安全にviewへ変換できるRangeを表すコンセプトである。
Rangeアダプタを適用するには、viewable_rangeである必要がある。
モデル
型Tがviewable_rangeのモデルとなるのは、Tがrangeのモデルであり、かつ以下のいずれかを満たす場合である。
remove_cvref_t<T>がviewのモデルであり、かつTからconstructible_from<remove_cvref_t<T>, T>である(ムーブ専用のviewの左辺値も安全に扱えるようにするための条件)remove_cvref_t<T>がviewのモデルではなく、Tが左辺値参照であるか、またはremove_reference_t<T>がmovableでありかつinitializer_listの特殊化ではない
viewでも左辺値でもないrangeの右辺値のうち、ムーブできないものはviewable_rangeのモデルにはならない。
例
#include <ranges>
#include <vector>
#include <initializer_list>
int main()
{
using V = std::vector<int>;
// 左辺値のRangeはviewable_range
static_assert(std::ranges::viewable_range<V&>);
// 右辺値でも、ムーブ可能なRangeならviewable_range
static_assert(std::ranges::viewable_range<V&&>);
// viewはそれ自体viewable_range
static_assert(std::ranges::viewable_range<std::ranges::empty_view<int>>);
// initializer_listの右辺値は、danglingを避けるためviewable_rangeにならない
static_assert(!std::ranges::viewable_range<std::initializer_list<int>>);
// 左辺値なら参照先が存続するのでviewable_rangeになる
static_assert(std::ranges::viewable_range<std::initializer_list<int>&>);
}
出力
バージョン
言語
- C++20
処理系
- Clang: 13.0.0 ✅
- GCC: 10.1.0 ✅
- ICC: ??
- Visual C++: 2019 Update 10 ✅
参照
- N4861 24 Ranges library
- C++20 ranges
- LWG Issue 3481
viewable_rangemishandles lvalue move-only views- C++23で、
viewの場合にconstructible_from<remove_cvref_t<T>, T>を要求するようコンセプト定義が変更され、ムーブ専用のviewの左辺値もviews::allで扱えるようになった
- C++23で、
- P2415R2 What is a
view? (本提案文書はC++20に遡って適用されている)