-
항목 1. 템플릿 형식 연역 규칙을 숙지하라.프로그래밍/Modern Effective c++ 2016. 3. 13. 23:54
auto는 템플릿에 대한 형식 연역을 기반으로 작동한다.
하지만 이것이 auto에 적용될 때 템플릿에 적용될 때보다 덜 직관적인 경우가 있다.
따라서 제대로 이해하기 위해서는 템플릿 형식 연역을 제대로 이해해야한다.
템플릿은 일반적으로 다음의 형태를 가진다.
template<typename T>
void f(ParamType param);f(expr); //호출
ParamType의 형태를 기준으로 세가지 경우를 살펴보자.경우 1. ParamType이 포인터 또는 참조 형식이지만, 보편참조는 아닌 경우.1. expr이 참조 형식이면 참조부분을 무시한다. --> 당연하다. expr이 참조형식인것은 자기한테만 중요할뿐 param에게는 아무의미가 없다.2. 그다음 expr의 형식을 ParamType에 대해 패턴 매칭 방식으로 대응시켜서 T의 형식을 결정한다.ex1)template<typename T>void f(T& param);int x = 27;const int cx = x;const int& rx = xf(x); --> T : int, param : int&f(cx); --> T : const int, param : const int&f(rx); --> T : const int, param : const int&ex2)template<typename T>void f(const T& param);int x = 27;const int cx = x;const int& rx = xf(x); --> T : int, param : const int&f(cx); --> T : int, param : const int&f(rx); --> T : int, param : const int&ex3)template<typename T>void f(T* param);int x = 27;const int* px = &x;f(&x); --> T : int, param : int*f(px); --> T : const int, param : const int*경우 2. ParamType이 보편참조인 경우.template<typename T>void f(T&& param);int x = 27;const int cx = x;const int& rx = x;f(x); --> x: 왼값, T : int&, param : int&f(cx); --> x: 왼값, T : int&, param : const int&f(rx); --> x: 왼값, T : int&, param : const int&f(27); --> x: 오른값, T: int, param : int&&이유는 항목 24에서 설명.경우 3. ParamType이 포인터도 아니고 참조도 아님.인수가 함수에 값으로 전달되는 상황.template<typename T>void f(T param);따라서 param은 주어진 인수의 복사본, 즉 완전히 새로운 객체. 이때문에 expr에서 T가 연역되는 과정에서 다음이 적용된다.1. expr이 참조형식이면 참조부분은 무시된다. --> 경우 1과 같이 당연하다.2. expr의 참조성을 무시한 후 만일 expr이 const이면 그 const 역시 무시한다.template<typename T>void f(T param);int x = 27;const int cx = x;const int& rx = xf(x); --> T : int, param : intf(cx); --> T : int, param : intf(rx); --> T : int, param : intparam은 expr과는 독립적인 새로운 객체이기 때문에 const는 당연히 사라진다.다음의 경우는 어떨까.template<typename T>void f(T param);const char* const ptr = "Fuck";f(ptr);이 경우 param은 ptr을 복사한 새로운 객체이므로 ptr자체의 const성은 사라진다.하지만 ptr이 가리키는 것의 const 성은 보존된다.--> param : const char*, T: const char*배열 인수함수에 배열을 전달하는 것은 배열이 포인터로 붕괴되는 결과를 가져온다.이때문에 배열의 크기를 알수 없게 되는데, 다음과 같이 참조로 전달하면template<typename T>void f(T& param);const char name[] = "FUCK";f(name);T는 const char [4]로, param은 const char (&) [4]로 연역된다. 따라서 배열의 크기를 알수 있다.이를 이용해서 다음과같이 배열에 담긴 원소의 개수를 연역하는 템플릿을 만들 수 있다.template<typename T, std::size_t[N]constexpr std::size_t arraySize(T (&) [N]) noexcept{return N;}constexpr로 선언하면 함수 호출의 결과를 컴파일 도중에 사용할 수 있게 된다. 따라서 다음과같이 사용할 수 있다.int keyVals[] = { 1, 3, 5, 7, 9, 11 };int mappedVals[arraySize(keyVals)];'프로그래밍 > Modern Effective c++' 카테고리의 다른 글
항목 3. decltype의 작동 방식을 숙지하라. (0) 2016.03.28 항목 2. auto의 형식 연역 규칙을 숙지하라. (0) 2016.03.21 1장 형식 연역 (0) 2016.03.13 0. 현재의 c++ (incomplete) (0) 2016.03.13