Item 2 : auto 의 타입 추론
auto의 타입 추론은 template의 타입 추론의 다른 형태
- auto 는 내부적(개념적)으로 템플릿 함수를 호출하여 T의 결과를 auto로 추론한다.
- auto x = 27;
- 위의 오토 선언은 아래의 템플릿함수와 함수 호출로 대체될 수 있다.
template<typename T> void func_for_x(T param); //auto는 T로 변화하고 void(ParamType) 형의 함수가 만들어 진다. func_for_x(27); //이 함수를 호출했을때 템플릿 함수의 타입추론 과정을 그대로 따라가면, //param이 int가 되고 T가 int로 매칭된다. 따라서 auto 는 int임을 추론할 수 있다.
Item 1 의 모든 내용은 auto에서 똑같이 적용됨
case 1 : 형식 지정자가 포인터 / 레퍼런스 인경우 (전역 레퍼런스 제외)
const auto& rx = x; template<typename T> void func_for_rx(const T& param); //auto가 T로 //auto 포함된 paramType이 그대로 T로 매칭되서 param의 타입으로 func_for_rx(x); //0호출시 T가 int가 되므로 auto 는 intrx의 타입은 const int&
case 2 : 형식 지정자가 전역 레퍼런스 인 경우.
- 대입되는 매개변수가 lvalue인 경우
auto&& urefLvalue = x; template<typename T> void func_for_urefLvalue(T&& param); func_for_urefLvalue(x); //호출시 T가 int&/ ParamType이 int& , auto가 int&로 변환되지만 //ParamType이 결과적으로 int&이므로 urefLvalue의 타입은 int&
- 대입되는 매개변수가 rvalue인 경우
auto&& urefRvalue = 27; template<typename T> void func_for_urefLvalue(T&& param); func_for_urefLvalue(27); //호출시 T는 int / ParamType은 int&&, //auto가 int, urefRvalue의 타입은 int&&
case 3 : 형식 지정자가 포인터 / 레퍼런스 둘 다 아닌 경우.
auto x = 27; //위에서 이미 언급
배열의 경우 (함수의 경우와 동일)
const char name[] = "Kim Ozt";
case 1
auto arr1 = name; template<typename T> void func_for_arr1(T param); func_for_arr1(name); //배열은 매개변수로 못받아서 *로 decay //T는 const char*로 / ParamType도 const char*
case 2
auto& arr2 = name; template<typename T> void func_for_arr1(T& param); func_for_arr1(name); //배열의 레퍼런스는 매개변수로 OK //T는 const char(&)[]로 / ParamType도 const char(&)[]
auto 의 타입 추론과 template의 타입추론의 차이점.
- 결론 : brace( {...} )를 포함한 초기화에서 auto와 template이 차이가 발생
brace를 포함한 초기화 ( C++11 이상 )
std::Initializer_list
- C++ 11이전에는 구조체/클래스/배열만 brace를 통한 초기화가 가능했다.
- C++ 11에서 std::Initializer_list 템플릿 클래스를 통해 확장
- initializer_list란 결국 임의의 타입의 임시 배열을 접근가능하게 하는 오브젝트
- STL의 기본 컨테이너를 포함한 모든 클래스에서 사용가능
특정 시점에서 자동 생성
braced-init-list가 리스트형 초기화에 사용되는 경우
vector<int> v1{ 1, 2, 3, 4, 5 }; //std::vector<int> v1(std::initializer_list<int>);
braced-init-list가 auto 변수에 바인딩 되는 경우
auto al = { 10, 11, 12 }; //std::initializer_list<int> al;
Uniform Initialization
- 기존의 C++에서 초기화 방식이 각 타입마다 제각각
- Initializer_list를 활용하여 모든 오브젝트 타입에 대해 동일한 방식(brace-init-list)으로 초기화가 가능하다.
- Uniform Initialization은 초기화 개량형을 통일하자는 Movement의 일종(?)
구조체, 클래스, primitive, stl 컨테이너 등 모든 타입을 brace-init-list로 초기화
struct AltStruct { AltStruct(int x, double y) : x_{ x }, y_{ y } // 초기화 목록에서도 { } 로 초기화 { } private: int x_; double y_; }; AltStruct as{ 2, 4.3 }; float b{ 1.f }; map<int, int> m1 { { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 } }; //출처:[C++11] Uniform intialization
위에서 언급한바 brace-init-list를 통한 초기화에서 auto의 경우 std::initializer_list로 타입 추론됨
- 실제 이 추론은 2번의 타입 추론을 거쳐 가능
- brace-init-list를 std::initializer_list로 변환하는 타입 추론
- std::initializer_list템플릿을 인자에 맞는 타입으로 변경하는 타입 추론
템플릿의 경우 auto와 같이 두번의 타입 추론을 하지 못함
- 이유는?
- Scott Meyers : "You might wonder why auto type deduction has a special rule for braced initializers, but template type deduction does not. I wonder this myself. Alas, I have not been able to find a convincing explanation."
- 문제는 템플릿에 brace-init-list로 타입 추론을 하려하면, 에러가 발생한다는 것!
auto x = {11, 23, 9}; //x's type is std::initialize_list<int> template<class T> void f(T param); f({11, 23, 9}); //error!
이 차이점을 주의해야 하는 경우
- Uniform Initialization을 auto에 적용시키려고 한 경우
- 원하는 구조체, 클래스, 타입 대신 무조건 std::initializer_list로 타입 추론 될 것이다.
- Uniform Initialization을 템플릿에 적용시키려고 한 경우
- 에러 발생
- C++14 에서
- auto 리턴 함수의 경우
- 이때 사용하는 auto의 추론방식은 template과 완전히 같다.
- 때문에 brace-init-list를 사용하면 에러가 발생한다.
auto createInitList() { return {1, 2, 3}; //error }
- 람다의 패러미터로 auto를 사용하는 경우
- 이 auto역시 template과 같은 방식으로 추론
- 때문에 brace-init-list를 사용하면 에러가 발생한다.
auto resetV = [&v](const auto& newValue){ v = newValue;}; resetV({1, 2, 3}); //error
- auto 리턴 함수의 경우
- Uniform Initialization을 auto에 적용시키려고 한 경우
'컴퓨터 > Modern Effective C++ 정리' 카테고리의 다른 글
Modern Effective C++ Item 12: 오버라이딩 함수에 override를 선언하자. (1) | 2015.03.24 |
---|---|
Modern Effective C++ Item 11 : Private 봉인술 <<< Delete 봉인술 (2) | 2015.03.24 |
Modern Effective C++ Item 10 : enum <<< enum class (0) | 2015.03.24 |
Modern Effective C++ Item 6 : auto로 안되면 명타초 쓰자 (0) | 2015.03.10 |
Modern Effective C++ Item 5 : auto는 우월하다 (0) | 2015.03.10 |