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を参照する非constxvalueでない(ムーブが起こる自己代入ではない)場合lhsはrcopyと等値である
rhsが非constxvalueならば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 ✅