最終更新日時(UTC):
が更新

履歴 編集

concept
<iterator>

std::indirectly_writable(C++20)

namespace std {
  template<class Out, class T>
  concept indirectly_writable = 
    requires(Out&& o, T&& t) {
      *o = std::forward<T>(t);
      *std::forward<Out>(o) = std::forward<T>(t);
      const_cast<const iter_reference_t<Out>&&>(*o) = std::forward<T>(t);
      const_cast<const iter_reference_t<Out>&&>(*std::forward<Out>(o)) = std::forward<T>(t);
    };
}

概要

indirectly_writableは、任意の型Outが間接参照演算子(operator*)によって型Tの値を書き込み(出力)可能であることを表すコンセプトである。

イテレータ型に限らず、ポインタ型、スマートポインタ型などがこのコンセプトのモデルとなることができる。

要件

このコンセプトを構成する4つの制約式は全て、等しさを保持することを要求しない。

const_castを用いる制約式は、右辺値の代入は可能だがconstな右辺値の代入ができないようなprvalueの非プロキシイテレータを弾くために存在している。これによって、間接参照がprvalueTそのもの、例えばstd::string)を返すようなイテレータ型はindirectly_writableのモデルとならない。

モデル

decltype((E)) == Tとなるような式E及びdereferenceableな型Outのオブジェクトoについて次の条件を満たす場合に限って、型Out, Tindirectly_writableのモデルである。

  • Out, Tが次の制約式のモデルとなる場合、式Eを上記(定義内)式のいずれかの形で出力した後で、*oは元のEの値と等値(equal)になる。
    • ただし、そのような出力の後でoが間接参照可能である必要はない。

indirectly_readable<Out> && same_as<iter_value_t<Out>, decay_t<T>>

Eの値カテゴリがxvalueの場合、上記式による出力後Eのオブジェクトは有効だが未規定な状態となる

備考

indirectly_writableのモデルとなるOutoperator*は出力(上記式による代入文の左辺に来ること)だけが唯一有効な使用法であり、indirectly_readableである必要はない。

#include <iostream>
#include <concepts>
#include <iterator>
#include <memory>
#include <vector>
#include <optional>

template<typename Out, typename T>
requires std::indirectly_writable<Out, T>
void f(const char* out, const char* t) {
  std::cout << out << " is indirectly writable " << t << std::endl;
}

template<typename Out, typename T>
void f(const char* out, const char* t) {
  std::cout << out << " is not indirectly writable " << t << std::endl;
}


struct writable {
  int& operator*();
};

struct not_writable {
  //prvalueを返す、出力不可能
  int operator*();
};


int main() {
  f<int*, int>("int*", "int");
  f<std::unique_ptr<int>, int&>("std::unique_ptr<int>", "int&");
  f<std::vector<int>::iterator, int&&>("std::vector<int>::iterator", "int&&");
  f<std::ostream_iterator<double>, double>("std::ostream_iterator<double>", "double");
  f<writable, int>("writable", "int");

  std::cout << "\n";
  f<std::vector<bool>::iterator, bool>("std::vector<bool>::iterator", "bool");
  f<std::optional<int>, int>("std::optional<int>", "int");
  f<not_writable, int>("not_writable", "int");
}

出力

int* is indirectly writable int
std::unique_ptr<int> is indirectly writable int&
std::vector<int>::iterator is indirectly writable int&&
std::ostream_iterator<double> is indirectly writable double
writable is indirectly writable int

std::vector<bool>::iterator is not indirectly writable bool
std::optional<int> is not indirectly writable int
not_writable is not indirectly writable int

バージョン

言語

  • C++20

処理系

関連項目

参照