일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- operator new
- 게임
- 비교 함수 객체
- 암시적 변환
- 영화 리뷰
- effective modern c++
- 함수 객체
- 메타테이블
- effective stl
- exception
- Effective c++
- 언리얼
- 다형성
- 참조자
- 반복자
- 스마트 포인터
- 영화
- 상속
- 티스토리챌린지
- more effective c++
- UE4
- lua
- 오블완
- reference
- resource management class
- Smart Pointer
- virtual function
- 예외
- implicit conversion
- c++
Archives
- Today
- Total
스토리텔링 개발자
[Effective Modern C++] 2. auto 타입 추론 규칙 본문
728x90
항목 2. auto의 형식 연역 규칙을 숙지하라
auto와 template의 타입 추론
- 한 가지 기이한 예외를 제외하면, auto 타입 추론이 곧 템플릿 타입 추론이다.
// 템플릿 타입 추론
// expr과 ParamType의 타입을 통해 T를 추론한다.
template<typename T>
void f(ParamType param);
f(expr); // 함수 실행
// auto 타입 추론
// auto : T와 동일한 역할
// 변수의 타입 지정자(type specifier) : ParamType과 동일한 역할
// 각각 아래의 주석 코드의 템플릿 타입 추론과 동일하다.
auto x = 27; // 타입 지정자 : auto
// template<typename T>
// void func_for_x(T param);
// func_for_x(27);
const auto cx = x; // 타입 지정자 : const auto
// template<typename T>
// void func_for_cx(const T param);
// func_for_cx(x);
const auto& rx = x; // 타입 지정자 : const auto&
// template<typename T>
// void func_for_rx(const T& param);
// func_for_rx(x);
- 그러므로 역시 세 가지 경우로 나뉜다.
- 타입 지정자가 포인터나 참조 타입이지만, 보편 참조(universal reference)는 아닌 경우
- 타입 지정자가 보편 참조인 경우
- 타입 지정자가 포인터도 참조도 아닌 경우
auto x = 27; // 경우 3
const auto cx = x; // 경우 3
const auto& rx = x; // 경우 1
auto&& uref1 = x; // 경우 2, 타입은 int&
auto&& uref2 = cx; // 경우 2, 타입은 const int&
auto&& uref3 = 27; // 경우 2, 타입은 int&&
- 배열과 함수 이름이 포인터로 붕괴되는 것 역시 동일하다.
const char name[] = "R. N. Briggs";
auto arr1 = name; // 타입은 const char*
auto& arr2 = name; // 타입은 const char (&)[13]
void someFunc(int, double);
auto func1 = someFunc; // 타입은 void (*)(int, double)
auto& func2 = someFunc; // 타입은 void (&)(int, double)
템플릿과 다른 한 가지 예외
- 초기값을 사용하여 int 변수를 선언하는 예
// C++98
int x1 = 27;
int x2(27);
// C++11
// 균일 초기화(uniform initialization) 지원
int x3 = { 27 };
int x4{ 27 };
- 하지만 고정된 형식 대신 auto를 사용하면 몇 가지 장점이 있으므로 auto로 변경 해보자.(항목 5 참조)
- 이 경우, 컴파일은 되지만, 의미가 달라진 것들이 생긴다!
auto x1 = 27; // 동일. 타입은 int, 값은 27
auto x2(27); // 동일. 타입은 int, 값은 27
auto x3 = { 27 }; // 변경됨. 타입은 std::initializer_list<int>, 값은 { 27 }
auto x4{ 27 }; // 변경됨. 타입은 std::initializer_list<int>, 값은 { 27 }
- auto의 특별한 타입 추론 규칙
- auto로 선언된 변수의 초기값(initializer)이 중괄호 쌍으로 감싸인 형태라면, std::initializer_list로 추론된다.
- 이 추론이 불가능할 경우 컴파일 에러가 발생한다.
auto x5 = { 1, 2, 3.0 } // T를 추론할 수 없으므로 컴파일 에러
- 사실 auto로 std::initializer_list를 추론하는 경우 두 가지 타입을 추론하게 된다.
- auto에 의한 타입 추론
- 추론된 타입인 std::initializer_list가 템플릿이므로 템플릿 타입 추론
- 즉, 위의 컴파일 에러의 경우 두 번째 타입 추론을 실패한 것이다.
- 이 타입 추론은 auto에서만 유효하다.
auto x = { 11, 23, 9 }; // std::initializer_list<int>로 타입 추론 성공
template<typename T>
void f(T param);
f({ 11, 23, 9 }); // 타입을 추론할 수 없어서 컴파일 에러
// 아래와 같이 바꾸어주면 된다.
template<typename T>
void f(std::initializer_list<T> param);
f({ 11, 23, 9 }); // std::initializer_list<int>로 타입 추론 성공
- 즉, 중괄호 초기값을 만나면 auto의 경우 std::initizlier_list라고 추론하지만, 템플릿은 그렇지 않다.
C++14에서의 auto 타입 추론
- auto는 함수 리턴 타입에도 사용할 수 있다.(항목 3 참조)
- 하지만, 이 경우 템플릿 타입 추론 규칙이 적용된다.
auto createInitList()
{
return { 1, 2, 3 }; // 타입 추론 불가능으로 컴파일 오류!
}
- 람다 매개변수로 auto가 사용될 때도 마찬가지 이유로 컴파일 에러가 발생한다.
std::vector<int> v;
...
auto resetV = [&v](const auto& newValue) { v = newValue; };
...
resetV({ 1, 2, 3 }); // 타입 추론 불가능으로 컴파일 오류!
728x90
'개발 > Effective Modern C++' 카테고리의 다른 글
[Effective Modern C++] 6. auto의 타입 추론 실패 (0) | 2025.02.12 |
---|---|
[Effective Modern C++] 5. 타입 명시보다 auto (0) | 2025.02.11 |
[Effective Modern C++] 4. 추론 타입 파악하기 (0) | 2025.02.10 |
[Effective Modern C++] 3. decltype (0) | 2025.02.07 |
[Effective Modern C++] 1. 템플릿 타입 추론 규칙 (0) | 2025.02.05 |
Comments