728x90
형식 연역
항목 1: 템플릿 형식 연역 규칙을 숙지하라
필요성 : 템플릿 형식 연역 규칙들이 auto의 문액에 적용 될 때 덜 직관적임
auto를 잘 활용하려면 템플릿 형식 연역을 이해하고 있어야 한다.
T, ParamType서로 다르게 연역된다.
template<typename T>
void f(ParamType param)
f(expr)
*위의 식은 아래에서 parameter를 말하기 위해서 사용한다.
- 보편 참조(universal reference)가 아닌 경우 ( 포인터 or 참조 형식 )
- 만일 expr이 참조 형식이면 참조 부분을 무시
- expr의 형식을 ParamType에 대해 패턴 부합(pattern-matching)방식으로 대응시켜 T의형식을 결정
template<typename T>
void f(T& param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x); // T는 int,
// param의 형식 int&
f(cx); // T는 const int,
// param의 형식은 const int&
f(rx); // T는 const int,
// param의 형식은 const int&
한정사는 T에 연역되기 때문에 const를 붙이지 않아도 안전하다. (둘째, 셋째)
변수의 참조성은 무시된다. (셋째)
template<typename T>
void f(const T& param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x); // T는 int,
// param의 형식 const int&
f(cx); // T는 int,
// param의 형식은 const int&
f(rx); // T는 int,
// param의 형식은 const int&
const T&로 바꾸었을 때,
이미 param이 const에 대한 참조로 되어 있기 때문에 연역 될 필요가 없다.
template<typename T>
void f(T* param);
int x = 27;
const int *px = &x;
f(&x); // T는 int,
// param의 형식 int*
f(cx); // T는 const int,
// param의 형식은 const int*
이미 Param 포인터이기 때문에 T에 연역 될 필요가 없다.
- ParamType이 보편 참조인 경우
만일 expr이 l-value이면, T와 ParamType 둘다 l-value참조로 연역된다. - r-value이면, 1의 경우와 같다.
template<typename T>
void f(T&& param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x); // T는 int&,
// param의 형식 int&
f(cx); // T는 int&,
// param의 형식은 int&
f(rx); // T는 int&,
// param의 형식은 int&
f(27); // T는 int
// param의 형식은 int&&
- ParamType이 보편 참조, 포인터 둘다 아닌 경우
- expr의 참조를 무시한다.
- const/volatile도 무시한다.
template<typename T>
void f(T param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x); // T는 int,
// param의 형식 int
f(cx); // T는 int,
// param의 형식은 int
f(rx); // T는 int,
// param의 형식은 int
const char* const ptr은 ptr을 const로 받기 때문에 수정이 가능하지 않은 ptr이므로 문자를 바꿀 수 없다.
하지만 연역하는 동안은 const ptr의 const는 연역이 되면서 사라지게 된다.
template<typename T>
void f(T param);
const char * const ptr = "Fun with Pointer";
f(ptr); // const char \* const 형식의 인수를 전달
배열 인수
배열형식과 포인터 형식은 다르기 때문에 배열이 배열을 가르키는 첫 원소로 붕괴하기 때문이다.
아래와 같은 경우 설명에서 말한 붕괴 법칙 때문에 잘 컴파일 된다.
const char name[] = "J. P. Briggs"; // const char[13]
const char * ptrToName = name; // 배열이 포인터로 붕괴된다.
void myFunc(int param[]); // 위 아래 코드는 동치이기 때문에 1번 규칙을 적용받는다.
void myFunc(int* param);
함수 인수
함수형식도 함수 포인터로 붕괴가 가능하다.
void someFunc(int, double);
template<typename T>
void f1(T param);
template<typename T>
void f2(T& name);
f1(someFunc); // param은 함수 포인터로 연역됨
f2(someFunc); // param은 함수 참조로 연역됨
728x90
'Language > effective modern C++' 카테고리의 다른 글
Effective modern C++ ( Auto ) (0) | 2021.10.16 |
---|---|
Effective modern C++ ( Auto ) (0) | 2021.10.16 |
Effective modern C++ ( 형식 언어 ) (0) | 2021.10.14 |
Effective modern C++ ( 형식 언어 ) (0) | 2021.09.26 |
Effective modern C++ ( 형식 언어 ) (0) | 2021.09.22 |
댓글