22
modern effective c++ 1장 형식 연역 - 서론 - 항목1.템플릿 형식 연역 규칙을 숙지하라

Modern effective cpp 항목1

Embed Size (px)

Citation preview

Page 1: Modern effective cpp 항목1

modern effective c++1장 형식 연역

- 서론

- 항목1.템플릿 형식 연역 규칙을 숙지하라

Page 2: Modern effective cpp 항목1

서론 – 형식연역(type deduction)

• 타입 추론 아님? (이하 타입 추론)

• C++98에서는 타입 추론에 관한 규칙들이 한 종류

• C++11 에서는 세 가지로 늘어남. • auto 를 위한 규칙• decltype 을 위한 규칙• 기존 규칙 약간 수정(템플릿 등등)

• type을 변경하면 다른 곳에도 영향을 미칠 수 있음. • 조심해야함…

• 이 장에서 auto와 decltype이 작동하는 방식을 알아보자!

Page 3: Modern effective cpp 항목1

항목 1: 템플릿 타입 추론 규칙을 숙지하라.

• auto 는 템플릿에 대한 타입추론을 기반으로 작동한다.• 덜 직관적인 경우가 있음.

• 알아보기 어렵다는 뜻…

Page 4: Modern effective cpp 항목1

항목 1: 템플릿 타입 추론 규칙을 숙지하라.

함수 템플릿의 선언의 예:

template<typname T>

void f(ParamType param);

f(expr);

• 여기서 두가지 추론이 사용되는데, 하나는 T에 대한 추론,

• 하나는 ParamType에 대한 추론이다.

Page 5: Modern effective cpp 항목1

항목 1: 템플릿 타입 추론 규칙을 숙지하라.

• ParamType에 const 나 &같은 참조자 수식어가 들어감.

• T 에는 타입이 들어간다.

template<typename T>

void f(const T& param);

int x = 0;

f(x); //T는 int , ParamType은 const &T

// 파라미터 타입은 const int& 로 번역됨.

Page 6: Modern effective cpp 항목1

항목 1: 템플릿 타입 추론 규칙을 숙지하라.

• 이 때, ParamType이 결정되는 과정은 세가지 경우로 나눈다. 1. ParamType 이 포인터나 참조 형식이지만 universal refernce는 아닌

경우.

2. ParamType이 universal reference인 경우.

3. ParamType이 포인터도 아니고 참조도 아닌경우.

Page 7: Modern effective cpp 항목1

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&

Page 8: Modern effective cpp 항목1

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&

Page 9: Modern effective cpp 항목1

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&

Page 10: Modern effective cpp 항목1

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*

Page 11: Modern effective cpp 항목1

1-2 ParamType이 보편참조일때.

• Universal reference 란?• lvalue reference와 rvalue reference 둘 다 가능한 상태

template <typname T>

void f(T&& param); // universal ref.

Page 12: Modern effective cpp 항목1

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&&

Page 13: Modern effective cpp 항목1

1-3ParamType이 포인터도 아니고 참조도 아님.

Template<typname T>

void f(T param);

• param은 주어진 인수의 복사본이 된다!

• 이전처럼, expr 부분이 참조이면, 참조는 무시된다.

• 참조성을 무시한후, const이면 const 역시 무시한다.

• volatile 이면 그것도 무시한다. (? 항목 40참조)

Page 14: Modern effective cpp 항목1

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

Page 15: Modern effective cpp 항목1

• 함수내에 전달되는 값은 무조건 복사되는 값이 된다.

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이 포인터도 아니고 참조도 아님.

Page 16: Modern effective cpp 항목1

• 포인터 자체는 복사되어 const성이 사라짐.

• 가리키는 대상에 대한 const성은 유지됨.

template <tyepname T>void f(T param);

const char* const ptr = “Fun with pointers”;

f(ptr); // 포인터값 복사됨

1-3ParamType이 포인터도 아니고 참조도 아님.

Page 17: Modern effective cpp 항목1

1-4 배열인수

• 배일과 포인터를 구분하지 않고 사용할 수 있는경우?

• 많은 경우 배열이 첫 원소를 가리키는 포인터로 decay된다.

• 그렇다면 템플릿에서는 어떨까?

Page 18: Modern effective cpp 항목1

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

Page 19: Modern effective cpp 항목1

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;}

Page 20: Modern effective cpp 항목1

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 )

Page 21: Modern effective cpp 항목1

항목 1: 템플릿 타입 추론 규칙을 숙지하라.

• 정리

• 은근 간단한데• 왼값 관련 특별규정에 유의…

• 포인터 decay 관련 해서 유의…

• 대체 어떻게 추론 된건지 템플릿 결과물을 알고 싶으면 항목 4 참조.

Page 22: Modern effective cpp 항목1

• 감사합니다.

• 출처• 책 : modern effective c++