std::assignable_from
std::assignable_from (대입 가능성 개념)
RHS가 지정한 타입과 값 범주(value category)의 표준 라이브러리 개념(concept)이에요. RHS 형태의 표현식을 LHS로 지정된 타입의 lvalue 표현식에 대입할 수 있는지를 명세해요. C++20부터 있어요.
출처: cppreference
본문
<concepts> 헤더에 정의돼 있어요.
template< class LHS, class RHS >
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>;
};
개념 assignable_from<LHS, RHS>는 RHS가 지정한 타입과 값 범주의 표현식이 LHS로 지정된 타입의 lvalue 표현식에 대입될 수 있음을 명세해요.
의미 요구사항
다음이 주어졌을 때:
lhs:decltype((lhs))가LHS인 객체lcopy를 가리키는 lvalue.rhs:decltype((rhs))가RHS인 표현식.rcopy:rhs와 같은 별개의 객체.
assignable_from<LHS, RHS>는 다음일 때만 모델링돼요.
std::addressof(lhs = rhs) == std::addressof(lcopy)(즉 대입 표현식이 왼쪽 피연산자를 가리키는 lvalue를 산출).lhs = rhs를 평가한 뒤:lhs가rcopy와 같음. 단rhs가lcopy를 가리키는 비-const xvalue(즉 자기 대입-이동)인 경우는 제외.rhs가 glvalue이면:- 비-const xvalue이면, 그것이 가리키는 객체는 유효하지만 불특정 상태에 있음.
- 그렇지 않으면 그것이 가리키는 객체는 수정되지 않음.
동등성 보존(Equality preservation)
표준 라이브러리 개념의 requires 표현식에서 선언된 표현식들은 (달리 명시되지 않는 한) 동등성 보존(equality-preserving)이어야 해요.
참고
대입이 전함수(total function)일 필요는 없어요. 특히 어떤 객체 x에 대입하면 다른 객체 y가 수정될 수 있다면, x = y는 =의 정의역에 속하지 않을 가능성이 커요. 이는 보통 오른쪽 피연산자가 왼쪽 피연산자에 (직접적이든 간접적이든) 소유될 때 일어나요(예: 노드 기반 자료구조에서 노드를 가리키는 스마트 포인터, 또는 std::vector<std::any> 같은 것).
예제를 보면요.
#include <atomic>
#include <concepts>
#include <string>
int main()
{
// 일반적인 기본 사용, lvalue 참조 대입을 확인
static_assert(std::is_assignable_v<int&, int>);
static_assert(std::assignable_from<int&, int>);
// 기본 타입은 rvalue에 대한 대입을 지원하지 않아요
static_assert(!std::is_assignable_v<int, int>);
static_assert(!std::assignable_from<int, int>);
// std::assignable_from은 모든 유효한 대입 표현식을 받아들이진 않아요:
// rvalue 참조 대입
static_assert(std::is_assignable_v<std::string&&, std::string>);
static_assert(!std::assignable_from<std::string&&, std::string>);
// rvalue 대입
static_assert(std::is_assignable_v<std::string, std::string>);
static_assert(!std::assignable_from<std::string, std::string>);
// std::atomic::operator= 는 값을 반환
static_assert(std::is_assignable_v<std::atomic<int>&, int>);
static_assert(!std::assignable_from<std::atomic<int>&, int>);
}
이렇게 assignable_from은 is_assignable보다 더 엄격해서, 대입 결과가 LHS 타입 그 자체로 돌아와야 해요.
참고 문헌
- C++23 표준 (ISO/IEC 14882:2024): 18.4.8 Concept assignable_from [concept.assignable]
- C++20 표준 (ISO/IEC 14882:2020): 18.4.8 Concept assignable_from [concept.assignable]