Upload
paul-myeongchan-kim
View
181
Download
1
Embed Size (px)
Citation preview
modern effective c++1장 형식 연역
- 서론
- 항목1.템플릿 형식 연역 규칙을 숙지하라
서론 – 형식연역(type deduction)
• 타입 추론 아님? (이하 타입 추론)
• C++98에서는 타입 추론에 관한 규칙들이 한 종류
• C++11 에서는 세 가지로 늘어남. • auto 를 위한 규칙• decltype 을 위한 규칙• 기존 규칙 약간 수정(템플릿 등등)
• type을 변경하면 다른 곳에도 영향을 미칠 수 있음. • 조심해야함…
• 이 장에서 auto와 decltype이 작동하는 방식을 알아보자!
항목 1: 템플릿 타입 추론 규칙을 숙지하라.
• auto 는 템플릿에 대한 타입추론을 기반으로 작동한다.• 덜 직관적인 경우가 있음.
• 알아보기 어렵다는 뜻…
항목 1: 템플릿 타입 추론 규칙을 숙지하라.
함수 템플릿의 선언의 예:
template<typname T>
void f(ParamType param);
f(expr);
• 여기서 두가지 추론이 사용되는데, 하나는 T에 대한 추론,
• 하나는 ParamType에 대한 추론이다.
항목 1: 템플릿 타입 추론 규칙을 숙지하라.
• ParamType에 const 나 &같은 참조자 수식어가 들어감.
• T 에는 타입이 들어간다.
template<typename T>
void f(const T& param);
int x = 0;
f(x); //T는 int , ParamType은 const &T
// 파라미터 타입은 const int& 로 번역됨.
항목 1: 템플릿 타입 추론 규칙을 숙지하라.
• 이 때, ParamType이 결정되는 과정은 세가지 경우로 나눈다. 1. ParamType 이 포인터나 참조 형식이지만 universal refernce는 아닌
경우.
2. ParamType이 universal reference인 경우.
3. ParamType이 포인터도 아니고 참조도 아닌경우.
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&
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&
1-1 ParamType 이 포인터나 참조 형식이지만universal refernce는 아닌경우.
• param이 const에 대한 참조로 간주되어 const는 T에서 제외됨.
• rx의 참조성은 무시된다.
template <tyepname T>void f(const T& param);
int x = 27;const int cx = x;const int& rx = x;
f(x) // int, const int&
f(cx) // int, const int&
f(rx) // int, const int&
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*
1-2 ParamType이 보편참조일때.
• Universal reference 란?• lvalue reference와 rvalue reference 둘 다 가능한 상태
template <typname T>
void f(T&& param); // universal ref.
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&&
1-3ParamType이 포인터도 아니고 참조도 아님.
Template<typname T>
void f(T param);
• param은 주어진 인수의 복사본이 된다!
• 이전처럼, expr 부분이 참조이면, 참조는 무시된다.
• 참조성을 무시한후, const이면 const 역시 무시한다.
• volatile 이면 그것도 무시한다. (? 항목 40참조)
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
• 함수내에 전달되는 값은 무조건 복사되는 값이 된다.
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이 포인터도 아니고 참조도 아님.
• 포인터 자체는 복사되어 const성이 사라짐.
• 가리키는 대상에 대한 const성은 유지됨.
template <tyepname T>void f(T param);
const char* const ptr = “Fun with pointers”;
f(ptr); // 포인터값 복사됨
1-3ParamType이 포인터도 아니고 참조도 아님.
1-4 배열인수
• 배일과 포인터를 구분하지 않고 사용할 수 있는경우?
• 많은 경우 배열이 첫 원소를 가리키는 포인터로 decay된다.
• 그렇다면 템플릿에서는 어떨까?
1-4 배열인수
• void f(T& param); 으로 선언했다면 실제로 전달!
• const char (&)[13] 으로 추론된다.
template <tyepname T>void f(T param);
const char name[] = “J. P. Briggs”;// const char[13]
const char * ptrToName = name;// decay
f(name); //const char*
// 비교void myFunc (int param[]);//포인터로 decay
1-4 배열인수
• 개멋있다…
int keyVals[] = { 1,2,3,4,5}
int sameSizeVals[ arraySize(keyVals) ]; //이런식으로 같은크기 선언도 가능
std::array<int, arraySize(keyVals)> sameSizeVals; //C++ style
noexcept 는 항목 14참고.
// 배열의 크기를 컴파일 시점에서 상수로 리턴하는 템플릿…template<typename T, size_t N>constexpr size_t arrSize(T(&)[N]) noexcept{
return N;}
1-5 함수 인수
• 함수형식도 함수 포인터로 decay 된다.
void somFunc(int, double);
template<typename T>void f1(T param);
template<typename T>void f2(T& param);
f1(somFunc); // param은 함수 포인터로 추론됨. // void (*)( int, double )
f2(somFunc); // param은 함수 참조로 연역됨.// void (&)( int, double )
항목 1: 템플릿 타입 추론 규칙을 숙지하라.
• 정리
• 은근 간단한데• 왼값 관련 특별규정에 유의…
• 포인터 decay 관련 해서 유의…
• 대체 어떻게 추론 된건지 템플릿 결과물을 알고 싶으면 항목 4 참조.
끝
• 감사합니다.
• 출처• 책 : modern effective c++