最終更新日時:
が更新

履歴 編集

variable
<ranges>

std::ranges::disable_sized_range(C++20)

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

処理系

参照