namespace std {
template<class LHS, class RHS>
concept assignable_from =
is_lvalue_reference_v<LHS> &&
common_reference_with<const remove_reference_t<LHS>&, const remove_reference_t<RHS>&> &&
requires(LHS lhs, RHS&& rhs) {
{ lhs = std::forward<RHS>(rhs) } -> same_as<LHS>;
};
}
概要
assignable_from
は、指定された型および値カテゴリRHS
から左辺値LHS
へ代入可能であることを表すコンセプトである。
モデル
まず、lhs
をdecltype((lhs))
がLHS
であるようなlcopy
オブジェクトを参照する左辺値(参照)、rhs
をdecltype((rhs))
がRHS
であるような式、rcopy
をrhs
と等値な別のオブジェクトとして定義する。
これらのlhs, rhs, lcopy, rcopy
について、以下の条件を満たす場合に限って、型LHS, RHS
はassignable_from
のモデルである。
addressof(lhs = rhs) ==addressof(lcopy)
となるlhs = rhs;
という式の評価の後で以下のことが成り立っているrhs
がlcopy
を参照する非const
xvalueでない(ムーブが起こる自己代入ではない)場合lhs
はrcopy
と等値である
rhs
が非const
xvalueならばrhs
が参照するオブジェクトの状態は有効だが未規定
- それ以外の場合で、
rhs
がglvalueならばrhs
が参照するオブジェクトは変更されない
rhs
がprvalueの場合、2つめの条件のいずれにも該当しない。これはコピー省略等の最適化を考慮したものである。
備考
代入操作では、引数型の一部の値が本コンセプトが要求する構文・意味論的制約を必ずしも満たしていなくても構わない。特に、あるオブジェクトx
への代入操作によって別のオブジェクトy
が変更される時、x, y
はその場合の=
の定義域に含まれない事がある。
あるLHS, RHS
についてそのような個別の値が存在していたとしても、そのことはそのLHS, RHS
がassignable_from
のモデルとなることを妨げない。
例
#include <iostream>
#include <concepts>
#include <vector>
#include <memory>
template<typename LHS, typename RHS>
requires std::assignable_from<LHS, RHS>
void f(const char* name, const char* arg) {
std::cout << name << " is assignable from " << arg << std::endl;
}
template<typename LHS, typename RHS>
void f(const char* name, const char* arg) {
std::cout << name << " is not assignable from " << arg << std::endl;
}
struct S {
S& operator=(const S&) = default;
S& operator=(S&&) = delete;
};
int main() {
f<int&, short>("int&", "short");
f<std::vector<int>&, std::vector<int>>("std::vector<int>&", "std::vector<short>");
f<std::unique_ptr<int>&, std::unique_ptr<int>>("std::unique_ptr<int>&", "std::unique_ptr<int>");
f<S&, S&>("S&", "S&");
std::cout << "\n";
f<std::unique_ptr<int>&, std::unique_ptr<int>&>("std::unique_ptr<int>&", "std::unique_ptr<short>&");
f<S&, S>("S&", "S");
}
出力
int& is assignable from short
std::vector<int>& is assignable from std::vector<short>
std::unique_ptr<int>& is assignable from std::unique_ptr<int>
S& is assignable from S&
std::unique_ptr<int>& is not assignable from std::unique_ptr<short>&
S& is not assignable from S
バージョン
言語
- C++20
処理系
- Clang: ??
- GCC: 10.1 ✅
- Visual C++: 2019 Update 3 ✅