std::assignable_from
<concepts>
concept assignable_from =
std::is_lvalue_reference_v <LHS> &&
std::common_reference_with <
const std::remove_reference_t <LHS>&,
const std::remove_reference_t <RHS>&> &&
requires(LHS lhs, RHS&& rhs) {
{ lhs = std::forward <RHS>(rhs) } -> std::same_as <LHS>;
The concept assignable_from<LHS, RHS>
specifies that an expression of the type and value category specified by RHS
can be assigned to an lvalue expression whose type is specified by LHS
.
[edit] Semantic requirements
Given
-
lhs
, an lvalue that refers to an objectlcopy
such that decltype((lhs)) isLHS
, -
rhs
, an expression such that decltype((rhs)) isRHS
, -
rcopy
, a distinct object that is equal torhs
,
assignable_from<LHS, RHS>
is modeled only if
- std::addressof (lhs = rhs) == std::addressof (lcopy) (i.e., the assignment expression yields an lvalue referring to the left operand);
- After evaluating lhs = rhs:
-
lhs
is equal torcopy
, unlessrhs
is a non-const xvalue that refers tolcopy
(i.e., the assignment is a self-move-assignment), - if
rhs
is a glvalue:- If it is a non-const xvalue, the object to which it refers is in a valid but unspecified state;
- Otherwise, the object it refers to is not modified;
-
[edit] Equality preservation
Expressions declared in requires expressions of the standard library concepts are required to be equality-preserving (except where stated otherwise).
[edit] Notes
Assignment need not be a total function. In particular, if assigning to some object x
can cause some other object y
to be modified, then x = y is likely not in the domain of =
. This typically happens if the right operand is owned directly or indirectly by the left operand (e.g., with smart pointers to nodes in a node-based data structure, or with something like std::vector <std::any >).
[edit] Example
#include <atomic> #include <concepts> #include <string> int main() { // Normal basic usage, checks lvalue reference assignment static_assert(std::is_assignable_v <int&, int>); static_assert(std::assignable_from<int&, int>); static_assert(std::is_assignable_v <std::string &, std::string >); static_assert(std::assignable_from<std::string &, std::string >); // Fundamental types don't support assignment to an rvalue static_assert(!std::is_assignable_v <int, int>); static_assert(!std::assignable_from<int, int>); // std::assignable_from doesn't accept all valid assignment expressions: // rvalue reference assignment static_assert(std::is_assignable_v <std::string &&, std::string >); static_assert(!std::assignable_from<std::string &&, std::string >); // rvalue assignment static_assert(std::is_assignable_v <std::string, std::string >); static_assert(!std::assignable_from<std::string, std::string >); // std::atomic::operator= returns by value static_assert(std::is_assignable_v <std::atomic <int>&, int>); static_assert(!std::assignable_from<std::atomic <int>&, int>); }
[edit] References
- C++23 standard (ISO/IEC 14882:2024):
- 18.4.8 Concept
assignable_from
[concept.assignable]
- 18.4.8 Concept
- C++20 standard (ISO/IEC 14882:2020):
- 18.4.8 Concept
assignable_from
[concept.assignable]
- 18.4.8 Concept
[edit] See also
(class template) [edit]