728x90
항목 3 : decltype의 작동 방식을 숙지하라
auto, decltype은 operator[]에 따라 다른 값을 돌려 줄 수 있다. ( 왜 그런지는 항목 6에서 확인 )
Widget w;
auto myWidget1& cw = w;
auto myWidget1 = cw; // auto의 형식 연역 :
// myWidget1의 형식 Widget
decltype(auto) myWidget2 = cw; // decltype 형식 연역 :
// const Widget&
그렇다면 이 2개를 어떻게 맞출 수 있을까?
C++11 : 후행 반환 형식(trailing return type)을 통해 auto의 타입형식을 decltype과 일치 시킬 수 있다.
// 아래 코드는 정련 할 필요가 있다.
template<typename Container, typename Index>
auto autoAndAceess(Container& c, Index i)
-> decltype(c[i])
{
authenticateUser();
return c[i];
}
C++14
// C++14 아주 정확한 것은 아님
template<typename Container, typename Index> // 정련이
auto authAndAceess(Container& c, Index i ) // 필요함
{
authenticateUser();
return c[i]; // 반환 형식은 c[i]로부터 연역된다.
}
std::deque<int> d;
authAndAccess(d, 5) = 10; // 이 코드는 컴파일이 되지 않는다.
여기서 auto는 int 반환한다. d[5]는 int&를 반환하지만, auto는 &를 무시하기 때문이다.
C++14는 decltype(auto)를 통해 int&를 연역 할 수 있다.
auto는 해당 형식이 연역되어야 함을 뜻하고
decltype은 형식 연역 규칙들이 적용되어야 함을 뜻한다.
위에 선언을 정련해보자!
template<typename Container, typename Index>
decltype(auto) authAndAccess(Container& c, Index i);
위의 선언방식에 Container& c는 l-value 참조이기 때문에 r-value를 넣을 수 없다.
하지만 넣을 경우를 대비하여 보편참조로 바꾸는 것이 옳다!
// C++14
template<typename Container, typename Index>
decltype(auto) authAndAccess(Container&& c, Index i) // 보편참조로 바꿈
{
authenticateUser();
return std::forward<Container>(c)[i]; // return 바꿈
}
// C++11
template<typename Container, typename Index>
auto authAndAccess(Container&& c, Index i)
-> decltype(std::forward<container>(c)[i]
{
authenticateUser();
return std::forward<Container>(c)[i];
}
또, 이 함수의 return값은 색인 값을 쓰는 방식으로 되어 있기 때문에 return 값도 바꿔주는 것이 더 좋다.
예상 밖의 결과를 가져 올 수 있는 경우
이름보다 복잡한 표현식이 되는 경우 원하지 않은 타입이 연역될 수 있다.
int x = 10;
decltype(x); // int;
decltype((x)); // int&;
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.22 |
Effective modern C++ ( 형식 언어 ) (0) | 2021.09.21 |
댓글