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の非プロキシイテレータを弾くために存在している。これによって、間接参照がprvalue(T
そのもの、例えばstd::string
)を返すようなイテレータ型はindirectly_writable
のモデルとならない。
モデル
decltype((E)) == T
となるような式E
及びdereferenceable
な型Out
のオブジェクトo
について次の条件を満たす場合に限って、型Out, T
はindirectly_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
のモデルとなるOut
のoperator*
は出力(上記式による代入文の左辺に来ること)だけが唯一有効な使用法であり、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
処理系
- Clang: ??
- GCC: 10.1
- Visual C++: 2019 Update 6