types_common_reference
types_common_reference (공통 참조 타입)
std::common_reference는 C++20부터 사용할 수 있는 타입 특성 템플릿이에요. 주어진 타입들 T... 모두가 변환되거나 바인딩될 수 있는 공통 참조 타입을 결정해요. 조건부 연산자와 비슷한 방식으로 동작해서, 여러 타입이 함께 쓰일 때 자연스러운 공통 타입을 찾는 데 유용해요.
출처: cppreference
본문
헤더 <type_traits>에 정의됨 |
||
|---|---|---|
template < class ... T > struct common_reference ; |
(C++20부터) |
T...의 공통 참조 타입, 즉 T...의 모든 타입이 변환되거나 바인딩될 수 있는 타입을 결정해요. 아래 규칙에 따라 그러한 타입이 존재하면 멤버 타입 type이 그 타입을 가리켜요. 그렇지 않으면 멤버 타입 type은 존재하지 않아요. T... 중 어떤 타입이 (cv 한정된 void를 제외한) 불완전 타입이면 동작은 정의되지 않아요.
참조 타입이 주어졌을 때, common_reference는 주어진 참조 타입들이 모두 바인딩될 수 있는 참조 타입을 찾으려고 해요. 하지만 그러한 참조 타입을 찾지 못하면 비참조 타입을 반환할 수도 있어요.
sizeof...(T)가 0이면 멤버 타입type은 없어요.sizeof...(T)가 1이면 (즉T...에 오직 하나의 타입T0만 있으면) 멤버 타입type은T0와 같은 타입을 가리켜요.sizeof...(T)가 2이면 (즉T...에 두 타입T1,T2가 있으면):S를T1과T2의 단순 공통 참조 타입(simple common reference type)이라고 해요. 아래 조건이 모두 만족되면 멤버 타입type은S를 가리켜요:T1과T2가 모두 참조 타입이고S가 잘 형성되었을 것
std::is_convertible_v<std::add_pointer_t<T1>, std::add_pointer_t<S>>와 std::is_convertible_v<std::add_pointer_t<T2>, std::add_pointer_t<S>>가 모두 true일 것 |
(C++23부터) |
|---|
- 그렇지 않고,
std::basic_common_reference<std::remove_cvref_t<T1>, std::remove_cvref_t<T2>, T1Q, T2Q>::type이 존재하면 (여기서TiQ는Ti의 cv 한정자와 참조 한정자를U에 더하는 단항 별칭 템플릿, 즉TiQ<U>는U에Ti의 cv 및 참조 한정자를 추가한 타입), 멤버 타입type은 그 타입을 가리켜요. - 그렇지 않고,
decltype(false ? val<T1>() : val<T2>())가 유효한 타입이면 (여기서val은 함수 템플릿template <class T> T val();), 멤버 타입type은 그 타입을 가리켜요. - 그렇지 않고,
std::common_type_t<T1, T2>가 유효한 타입이면 멤버 타입type은 그 타입을 가리켜요. - 그렇지 않으면 멤버 타입
type은 없어요. sizeof...(T)가 2보다 크면 (즉T...가T1, T2, R...으로 구성되면),std::common_reference_t<T1, T2>가 존재할 때,std::common_reference_t<std::common_reference_t<T1, T2>, R...>가 존재하면 멤버 타입type은 그 타입을 가리켜요. 그 외의 모든 경우에는 멤버 타입type이 없어요.
두 참조 타입 T1과 T2의 단순 공통 참조 타입은 다음과 같이 정의돼요.
T1이cv1 X&이고T2가cv2 Y&이면 (즉 둘 다 lvalue 참조 타입): 단순 공통 참조 타입은decltype(false ? std::declval<cv12 X&>() : std::declval<cv12 Y&>())이에요. 여기서cv12는cv1과cv2의 합집합이에요. 이 타입이 존재하고 참조 타입이면 그 타입이 단순 공통 참조 타입이 돼요.T1과T2가 모두 rvalue 참조 타입이면:T1&와T2&의 단순 공통 참조 타입(이전 항목에 따라 결정)이 존재한다면, 그 타입에 대응하는 rvalue 참조 타입을C라고 해요.std::is_convertible_v<T1, C>와std::is_convertible_v<T2, C>가 모두true이면T1과T2의 단순 공통 참조 타입은C예요.- 그렇지 않으면, 두 타입 중 하나는 lvalue 참조 타입
A&이고 다른 하나는 rvalue 참조 타입B&&이에요 (A와B는 cv 한정될 수 있어요).A&와B const&의 단순 공통 참조 타입을D라고 해요.D가 존재하고std::is_convertible_v<B&&, D>가true이면 단순 공통 참조 타입은D예요. - 그렇지 않으면 단순 공통 참조 타입은 없어요.
위에서 사용된 false ? X : Y 형태의 표현식 타입에 대한 정의는 조건부 연산자를 참고하세요.
멤버 타입
| 멤버 타입 | 설명 |
|---|---|
type |
모든 T...에 대한 공통 참조 타입 |
도우미 타입
template < class ... T >
using common_reference_t = std::common_reference<T...>::type;
template < class T, class U, template <class> class TQual, template <class> class UQual >
struct basic_common_reference {};
클래스 템플릿 basic_common_reference는 사용자 정의 타입(주로 프록시 참조)에 대해 common_reference의 결과를 바꿀 수 있게 하는 커스터마이즈 포인트예요. 기본 템플릿은 비어 있어요.
특수화
프로그램은 std::is_same_v<T, std::decay_t<T>>와 std::is_same_v<U, std::decay_t<U>>가 모두 true이고 T 또는 U 중 적어도 하나가 프로그램 정의 타입에 의존할 때, std::basic_common_reference<T, U, TQual, UQual>의 처음 두 매개변수 T와 U에 대해 특수화할 수 있어요.
그러한 특수화에 type이라는 멤버가 있다면, 그 멤버는 공개적이고 모호하지 않아야 하며 TQual<T>와 UQual<U>가 모두 변환될 수 있는 타입을 가리켜야 해요. 또한 std::basic_common_reference<T, U, TQual, UQual>::type과 std::basic_common_reference<U, T, UQual, TQual>::type은 같은 타입을 가리켜야 해요.
프로그램은 세 번째나 네 번째 매개변수에 대해 basic_common_reference를 특수화할 수 없고, common_reference 자체도 특수화할 수 없어요. 이러한 규칙을 위반하여 특수화를 추가하면 동작이 정의되지 않아요.
표준 라이브러리는 다음과 같은 basic_common_reference 특수화를 제공해요.
std::basic_common_reference<std::pair> (C++23) |
두 pair의 공통 참조 타입을 결정함 (클래스 템플릿 특수화) |
|---|---|
std::basic_common_reference<tuple-like> (C++23) |
튜플과 튜플 유사 타입의 공통 참조 타입을 결정함 (클래스 템플릿 특수화) |
std::basic_common_reference<std::reference_wrapper> (C++23) |
reference_wrapper와 비-reference_wrapper의 공통 참조 타입을 결정함 (클래스 템플릿 특수화) |
참고 사항
| 기능 테스트 매크로 | 값 | 표준 | 기능 |
|---|---|---|---|
__cpp_lib_common_reference |
202302L | (C++23) | std::common_reference_t of std::reference_wrapper를 참조 타입으로 만듦 |
예제
#include <concepts>
#include <type_traits>
static_assert(
std::same_as<
int&,
std::common_reference_t<
std::add_lvalue_reference_t<int>,
std::add_lvalue_reference_t<int>&,
std::add_lvalue_reference_t<int>&&,
std::add_lvalue_reference_t<int>const,
std::add_lvalue_reference_t<int>const&
>
>
);
int main() {}
같이 보기
common_type (C++11) |
타입 그룹의 공통 타입을 결정함 (클래스 템플릿) |
|---|---|
common_reference_with (C++20) |
두 타입이 공통 참조 타입을 공유함을 지정함 (컨셉) |
common_reference (C++26) |
반영된 타입 시퀀스의 공통 참조 타입을 결정함 (함수 템플릿) |