2. 서론 – 형식연역(type deduction)
• 타입 추론 아님? (이하 타입 추론)
• C++98에서는 타입 추론에 관한 규칙들이 한 종류
• C++11 에서는 세 가지로 늘어남.
• auto 를 위한 규칙
• decltype 을 위한 규칙
• 기존 규칙 약간 수정(템플릿 등등)
• type을 변경하면 다른 곳에도 영향을 미칠 수 있음.
• 조심해야함…
• 이 장에서 auto와 decltype이 작동하는 방식을 알아보자!
3. 항목 1: 템플릿 타입 추론 규칙을 숙지하라.
• auto 는 템플릿에 대한 타입추론을 기반으로 작동한다.
• 덜 직관적인 경우가 있음.
• 알아보기 어렵다는 뜻…
4. 항목 1: 템플릿 타입 추론 규칙을 숙지하라.
함수 템플릿의 선언의 예:
template<typname T>
void f(ParamType param);
f(expr);
• 여기서 두가지 추론이 사용되는데, 하나는 T에 대한 추론,
• 하나는 ParamType에 대한 추론이다.
5. 항목 1: 템플릿 타입 추론 규칙을 숙지하라.
• ParamType에 const 나 &같은 참조자 수식어가 들어감.
• T 에는 타입이 들어간다.
template<typename T>
void f(const T& param);
int x = 0;
f(x); //T는 int , ParamType은 const &T
// 파라미터 타입은 const int& 로 번역됨.
6. 항목 1: 템플릿 타입 추론 규칙을 숙지하라.
• 이 때, ParamType이 결정되는 과정은 세가지 경우로 나눈다.
1. ParamType 이 포인터나 참조 형식이지만 universal refernce는 아닌
경우.
2. ParamType이 universal reference인 경우.
3. ParamType이 포인터도 아니고 참조도 아닌경우.
7. 1-1 ParamType 이 포인터나 참조 형식이지만 universal
refernce는 아닌경우.
• ParamType 이 포인터나 참조 형식이지만 universal refernce는 아닌경우.
1. 만일 expr부분이 참조 형식이면 참조 부분을 무시한다.
2. 그 다음 expr의 형식을 pattern-matching 방식으로 결정한다.
예>
template <tyepname T>
void f(T& param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x) // int, int&
f(cx) // const int, const int&
f(rx) // const int, const int&
8. 1-1 ParamType 이 포인터나 참조 형식이지만
universal refernce는 아닌경우.
• 둘째, 셋째 호출에서 T가 const int가 되기 때문에 매개변수는
자동으로 const int& 가 된다. 개이득!
• const-ness가 유지된다.
• 세 번째에서 T에 &가 무시된다는것도 명심.
template <tyepname T>
void f(T& param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x) // int, int&
f(cx) // const int, const int&
f(rx) // const int, const int&
10. 1-1 ParamType 이 포인터나 참조 형식이지만
universal refernce는 아닌경우.
• 포인터는 const int*로 잘 해석됨.
template <tyepname T>
void f(T* param);
int x = 27;
const int *px = &x;
f(&x); // int, int*
f(px); // const int, const int*
11. 1-2 ParamType이 보편참조일때.
• Universal reference 란?
• lvalue reference와 rvalue reference 둘 다 가능한 상태
template <typname T>
void f(T&& param); // universal ref.
12. 1-2 ParamType이 보편참조일때.
• 이 부분은 항목24에서 다시 설명한대요…
template< typename T>
void f(T&& param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x); //x는 lvalue, int&, int&
f(cx); //cx는 lvalue, const int& , const int&
f(rx); //rx는 lvalue, const int& , const int&
f(27); //27은 rvalue, int, int&&
13. 1-3ParamType이 포인터도 아니고 참조도 아님.
Template<typname T>
void f(T param);
• param은 주어진 인수의 복사본이 된다!
• 이전처럼, expr 부분이 참조이면, 참조는 무시된다.
• 참조성을 무시한후, const이면 const 역시 무시한다.
• volatile 이면 그것도 무시한다. (? 항목 40참조)
14. 1-3ParamType이 포인터도 아니고 참조도 아님.
• const 값을 지정해도, param은 const가 아니다.
template <tyepname T>
void f(T param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x) // int, int
f(cx) // int, int
f(rx) // int, int
15. • 함수내에 전달되는 값은 무조건 복사되는 값이 된다.
template <tyepname T>
void f(T param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x) // int, int
f(cx) // int, int
f(rx) // int, int
1-3ParamType이 포인터도 아니고 참조도 아님.
16. • 포인터 자체는 복사되어 const성이 사라짐.
• 가리키는 대상에 대한 const성은 유지됨.
template <tyepname T>
void f(T param);
const char* const ptr =
“Fun with pointers”;
f(ptr); // 포인터값 복사됨
1-3ParamType이 포인터도 아니고 참조도 아님.
17. 1-4 배열인수
• 배일과 포인터를 구분하지 않고 사용할 수 있는경우?
• 많은 경우 배열이 첫 원소를 가리키는 포인터로 decay된다.
• 그렇다면 템플릿에서는 어떨까?