본문 바로가기
Game DevTip/C++

5. C++ auto & decltype에 대해서.

by LIKE IT.라이킷 2024. 12. 5.

 

1. auto 타입 지정자

  • auto는 컴파일러에서 초기값으로 타입을 추론하고 타입을 결정짓는 타입이다.
    즉, 쉽게 이야기 하자면 해당 객체의 타입을 컴파일러가 알아서 결정해줌.

-> 때문에 무조건 auto 같은 경우에는 선언 시에 초기값이 있어야 한다.

auto item = val1 + val2; 	//item은 val1 + val2을 이용해 타입을 추론해 초기화.
  • 만약 item 변수를 함수가 호출해서 사용할 때 호출값이 double형(소수점)이면, auto는 double로,
    int형(정수)라면 int형으로 초기화 시킨다.

다만 여기에는 약간의 제약이 있는데...

auto i = 0, *p = &i;		//i는 int, p는 int에 대한 포인터로 추론될 예정이다.
auto s2 = 0, pi = 3.14;		//error! : s2, pi간 타입이 불일치하다.

 

위에 예시처럼 하나의 auto로 여러개의 객체를 생성할 때 그 값들이
모두 똑같은 타입으로 추론이 가능할 값을 가지고 있어야만 한다.

  • 즉, auto int, int;이나 auto double, double;은 되지만
    auto int, double;은 안된다는 이야기.

1-1. 참조자, const와 auto

  • 컴파일러 추론이 항상 정확한것은 아니다.
    때문에 컴파일러에서는 일반적인 초기화 규칙에 맞추기 위해서 타입을 조정하려고 한다.
int i = 0, &r = i;
auto a = r; 		//a는 int이다.(r은 i에 대한 참조자이기 때문.)
  • 참조자를 초기값으로 사용하면 그 초기값은 참조가 가리키는 대상의 객체 타입이 된다.

또한 auto에서는 일반적으로 상위 const를 무시한다.

  • 단, 초기값이 const에 대한 포인터 일 때처럼
    일반적으로 초기화 해서 하위 const는 유지한다.
int  i = 0;
const int ci = i, &cr = ci;
auto b = ci;				//b는 int이다.(ci에서 상위 const를 버림.)
auto c = cr;				//c는 int이다.(cr은 cosnt가 상위인 ci에 대한 별칭이다.)
auto d = &i;				//d는 int*이다.(int객체에 &를 적용하면 int*이기 때문.
auto e = &ci;				//e는 const int* 이다.(const 객체에 &를 적용하면 하위 const이다.)
  • 만약 추론할 타입에 상위 cosnt가 있으려면 명시적으로 지정해야 한다.(아래처럼)
const auto f = ci; //ci에서 추론한 타입은 int이다. 즉, f는 const int 타입이다.

 

또한 auto로 추론한 타입이 참조자가 되게 할 수도 있다.

auto &g = ci;			//g는 ci를 가리키는 const int&이다.
auto &h = 42;			//error! : 참조자는 숫자(상수)와 결합이 안된다.
const auto &j = 42; 	//const 참조8자는 상수와 결합이 가능하다.
  • 참고로 auto로 추론한 타입이 참조자가 되게 할 때, 초기값에서 상위 const를 무시한다.
    (일반적으로 참조자를 초기값과 결합 시에 const는 상위가 아니라 하위다.)

또한 auto는 일반적으로 초기값에 대해서 auto로 추론한 타입은 반드시 일치해야 한다.

 auto k = ci, &L = i;		//k는 int, L은 int&이다.
 auto &m = ci, *p = &ci;	//m은 const int&이고, p는 const int에 대한 포인터이다.
 auto &n = i, *p2 = &ci; 	//error! : i에서 추론한건 int이지만, &ci에서 추론한건 cosnt int이다.

2. decltype 타입 지정자

  • decltype은 쉽게 말해서 auto와 비슷하게 보일수 있지만,
    decltype 타입 지정자는 명시된 대상 의 타입을 추론한다는 것이 auto와 다른 점이다.
    "decltype (대상)"형태를 제공하면 대상의 타입을 추론해서 리턴합니다.
  • (*auto는 선언된 대상의 초기화 표현을 통해서 컴파일러에게 추론을 요청함.)

일단 decltype을 변수가 아닌 표현식에 적용하면
해당 표현식에서 반환하는 타입을 얻는다.

decltype (r + 0, r - 2) value_name;
  • 예시 몇가지
int i = 42, *p = &i, &r = i;
decltype (r+0) b;			// 덧셈은 int를 반환하므로 b는 초기화하지 않은 int이다.
decltype (*p) c;			// Error! : c는 int&이므로 초기화를 해야한다.
decltype (i);				// int 형이다.
decltype ((i));				// const int형이다.
  • 표현식에 적용한 decltype은 참조자 일 수도 있다.
    때문에 일부 표현식에서 decltype을 적용하면 참조자 타입을 반환한다.
  • 일반적으로 decltype에서는 대입의 왼쪽 피연산자가 될 수있다
    객체를 반환하는 표현식에 대해서는 참조자 타입을 반환한다.
  • 또한 대상의 대한 괄호(마지막 코드 예시)가 2개가 겹친경우
    (내부대상을 한번 더 감싸는 경우)

    이는 const 타입으로 인식하라는 것과 같은 뜻이다.

약간 특이한 점이 있다면..

  • 템플릿 같이 컴파일 시간내에 타입을 추론해야 하는 경우에는
    auto보단 decltype을 더 권고하기도 한다.

2-1. C++14부터 decltype의 달라진 점들

이쯤에서 약간 궁금한 점이 생기는데,
과연 decltype(auto)처럼 명시된 대상의 객체가 auto일 경우는 안되는 것일까?
-> 이건 C++14부터 지원한다.
(decltype 자체가 c++11이상 부터 지원하는데이런 기능은 14부터 지원.)

그 예시를 한번 보기위해 따로 다른 블로그 글을 참고해서 가지고 와봤다.
출처 : https://jungwoong.tistory.com/55

// c++ 11에서의 decltype 구현
template<typename T1, typename T2>
auto TemplatePlus(T1&& right, T2&& left) -> decltype(right + left)
{
    return right + left;
}
// c++ 11에서는 명시적으로 리턴 타입의 표현식을 후행 반환 타입에 기입 해야 함.

//--------------------------------------------------------------------------

// c++ 14에서의 decltype 구현
template<typename T1, typename T2>
decltype(auto) TemplatePlus(T1&& right, T2&& left)
{
    return right + left;
}
// c++ 14부터는 decltype에 auto를 추가해서 간결하게 사용가능하도록 지원되도록 바뀜.


int main()
{
    int a = 100;
    // TemplatePlus(10.3, a) 리턴 타입은 double로 추론됩니다.
    auto value = TemplatePlus(10.3, a);
    
    return 0;
}

 

예제를 보면 TemplatePlus 템플릿 함수는 템플릿 인자
T1, T2에 의해서 리턴값이 정해지는 함수이다.

 

decltype과 auto를 통해서 컴파일 타임에 T1, T2로 구성된
리턴 값의 타입을 추론하도록 컴파일러에게 지시할 수 있다.

// visual studio 2019에서는 이렇게 선언해도 수행가능
template<typename T1, typename T2>
auto TemplatePlus(T1&& right, T2&& left)
{
    return right + left;
}
  • 참고로 visual studio 2019에서는 이렇게
    decltype없이 auto로만 선언해도 정상적으로 작동한다고 한다.

그래서 그런지 decltype없이 간단히 auto로만 쓰려고 하는 것이 최근 추세이지만,
여전히 예전 코드 파일들을 들여다보면 decltype을 계속해서 쓰고있기에
필수적으로 기본적인 이런 쓰임법은 알고는 있어야 한다고 생각한다.

 

또 람다함수에서 특히 이 decltype과 auto가 정말 많이 쓰이는데,
아직... 람다함수를 제대로 모르기에..ㅋ;;;
좀 배우고나서 나중에 쓰고서 여기 아래 링크를 걸어두겠다.

반응형

'Game DevTip > C++' 카테고리의 다른 글

6. C++ string 타입에 대해서  (0) 2024.12.05
4. C++ Typedef(타입 별칭)에 대해서  (0) 2024.12.05
3. C++ constexpr에 대해서  (1) 2024.12.05
2. C++ const에 대하여  (0) 2024.12.05
1. C++ 변수사용 Tip에 대해서.  (0) 2024.12.05

댓글