namespace std::ranges {
template<class>
inline constexpr bool disable_sized_range = false;
}
概要
disable_sized_rangeは、sized_rangeを無効化するカスタマイゼーションポイントである。
sized_rangeコンセプトの構文要件を満たすが意味論要件を満たさないような型Tがあるとき、disable_sized_range<T>がtrueとなるように特殊化することでranges::sizeの引数にできないようにして、sized_rangeを無効化する。
具体的には、大きさを求めることはできるが、その計算量が償却定数にならないようなRangeが該当する。
要件
- cv修飾のないプログラム定義型に対して、この変数テンプレートを特殊化することが許可される。
- そのような特殊化は定数式で使用可能であり、
const bool型を持つ必要がある。
- そのような特殊化は定数式で使用可能であり、
例
#include <ranges>
#include <iostream>
#include <forward_list>
#include <iterator>
#include <cstddef>
// std::forward_listをラップしたRange。
// size()メンバを持つが、要素を数えるため計算量は要素数に比例する(償却定数ではない)
struct MyRange {
std::forward_list<int> data;
auto begin() { return data.begin(); }
auto end() { return data.end(); }
std::size_t size() const {
return static_cast<std::size_t>(std::distance(data.begin(), data.end()));
}
};
// size()の計算量が償却定数でないため、sized_rangeから除外する
template <>
inline constexpr bool std::ranges::disable_sized_range<MyRange> = true;
int main()
{
// disable_sized_rangeをtrueに特殊化したため、
// size()メンバを持っていてもsized_rangeのモデルにはならない
static_assert(!std::ranges::sized_range<MyRange>);
// rangeとしては使える
MyRange r{{1, 2, 3}};
for (int x : r) {
std::cout << x;
}
std::cout << std::endl;
}
出力
123
バージョン
言語
- 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 3183. Normative permission to specialize Ranges variable templates
- C++20で、プログラム定義型に対してこの変数テンプレートを特殊化してよいという規範的な許可が明記された