[Modern C++] 16.3. decltype

윤정민·2023년 8월 22일
0

C++

목록 보기
43/46

1. decltype

  • decltype이름의 함수처럼 사용됨
  • 타입을 알고자 하는 식의 타입으로 치환
    • 전달된 식이 괄호로 둘러쌓이지 않은 식별자 표현식이어야 함
    • 식별자 표현식이 아닌 식을 전달한다면 해당 식의 값의 종류에 따라 다르게 치환됨
#include <iostream>

int main()
{
	//decltype은 타입을 알고자 하는 식의 타입으로 치환됨
	//decltype에 전달된 식이 괄호로 둘러쌓이지 않은 식별자 표현식이라면 해당 식의 타입을 얻을 수 있음
	//식별자 표현식: 어떠한 연산을 하지않고 단순히 객체 하나만을 가리키는 식
	int a = 3;
	decltype(a) b = 2; // a가 int형이니  decltype(a)은 int로 치환됨

	int& r_a = a; //a의 레퍼런스를 r_a에 넣어줌
	decltype(r_a) r_b = b; // r_a가 int&형이니 decltype(r_a)은 int&형으로 치환됨

	return 0;
}

2. Value Category

  • C++에는 5가지의 값 카테고리가 존재함
  • 두 가지의 유무를 통해 나눌 수 있음
    • 정체를 알 수 있는가?
    • 이동시킬 수 있는가?



2.1. lvalue

  • 이름을 가진(주소값을 취할 수 있는) 대부분의 객체들
  • 타입과 값 카테고리가 다른 개념이라는 것을 주의하자

2.2. prvalue

  • 주소값을 취할 수 없는 값
    • &연산자 사용 불가
  • 식의 좌측에 올 수 없음
  • 우측값 레퍼런스와 상수 좌측값 레퍼런스를 초기화 하는데 사용할 수 있음

2.3. xvalue

  • 좌측값 처럼 주소값을 취할 수 있지만 이동도 가능한 값(ex. std::move(x))

2.4. decltype의 변환

  • xvalue : decltypeT&&
  • lvalue : decltypeT&
  • prvalue : decltypeT
  • prvalue 예시 코드
itn a, b;
decltype(a + b) c; //a+b식의 실제 타입인 int 로 추론
  • 식별자 표현식이 아닌 예시 코드
    • (a)는 식별자 표현식이 아님
      • 주소값 연산자를 사용 가능
      • 이동이 불가능
    • int로 추론될 것 같지만 int&로 추론됨
int a;
decltype((a)) b;

3. auto와 차이점

  • auto는 정확한 타입을 표현하지 않음
    • const같은 추가 지정자를 읽지 않음
    const int i = 4;
    auto j = i;         // int j = i;
    decltype(i) k = i;  // const int k = i;
    • 배열 타입을 명시적 포인터로 변환
    int arr[10];
    auto arr2 = arr; // int* arr2 = arr;
    decltype(arr) arr3; // int arr3[10];
  • 반면 decltype은 정확한 타입 전달이 가능

4. declval

  • decltype과 달리 <utilty>에 정의된 함수
  • T의 생성자를 직접 호출하지 않더라도 T가 생성된 객체를 나타낼 수 있음
    • 생성자가 존재하지 않더라도 T()를 한 것과 같은 효과를 낼 수 있음
  • 실제 런타임에 사용하면 오류가 난다는 점을 고려하자

    C++14부터 함수의 리턴타입을 컴파일러가 알아서 유추해주는 기능이 추가되어 함수의 리턴타입을 auto로 지정해주면 된다. 그렇다고 declval의 쓰임새가 없어진 것은 아니다. 이를 사용해 템플릿 메타프로그래밍 기법을 사용할 수 있다.

profile
그냥 하자

0개의 댓글