티스토리 뷰
[Effective Modern C++] 항목 3. decltype의 작동 방식을 숙지하라
pppgod 2019. 9. 2. 21:19decltype 이라는 키워드는 객체가 주어졌을때, 그 객체의 타입을 알려준다. 예시를 보자.
const int i = 0; // decltype(i)는 const int
MyClass object; // decltype(object)는 MyClass
위와 같이 객체의 타입을 알려주는데, 가끔 생각한대로 동작하지 않는 경우가 있다.
특이한 작동 방식
먼저 코드를 보자.
template<typename Container, typename Index>
auto authAndAccess(Container& c, Index i) -> decltype(c[i])
{
authenticateUser();
return c[i];
}
위에서 보이는 함수처럼 auto 와 decltype 을 이용한 방식을 후행 반환 형식이라고 한다. 후행 반환 형식으로 선언한 함수의 반환 타입은 decltype 에 주어진 객체의 타입이 된다. 여기서는 c[i] 의 타입이다.
그런데 만약 c[i] 의 반환 타입이 T& 인 경우라면 생각한대로 동작하지 않는다. 그 이유는 항목 1의 형식 연역 규칙 3에 의해 참조성이 사라지기 때문이다.
형식 연역을 위한 decltype(auto)
위 코드의 문제를 해결하는 방법은 아주 간단하다. decltype 과 auto 를 합치면 된다. decltype(auto) 는 말 그대로 auto 로 형식을 연역하는데 그 과정에서 decltype의 규칙을 사용하겠다는 의미다. 문제를 수정한 코드는 다음과 같다.
template<typename Container, typename Index>
decltype(auto)
authAndAccess(Container& c, Index i)
{
authenticateUser();
return c[i];
}
이 코드는 앞서 이야기한 문제를 해결한다. 하지만 두가지 문제점이 존재한다. 하나는 Container 가 우측값으로 넘어오는 경우이고 나머지 하나는 아주 예외적인 경우이다.
우측값 참조를 위한 보편참조
위의 코드에서 c는 우측값으로 넘어 올 수 없다. c[i] 가 참조인 경우 Container 는 const 로 지정될 수 없기 때문이다. 이때 사용하는 방법이 바로 보편참조이다. Container& c 파라미터를 Container&& c 로 바꾸기만 하면 된다. 최종 완성코드는 다음과 같다.
template<typename Container, typename Index>
decltype(auto)
authAndAccess(Container&& c, Index i)
{
authenticateUser();
return std::forward<Container>(c)[i];
}
forward 는 move 와 비슷한 함수로 항목 25를 참고하자.
두번째 특이한 예외 상황
두번째로 생길 수 있는 문제는 코드로 확인하자.
decltype(auto) f1()
{
int x = 0;
...
return x;
}
decltype(auto) f2()
{
int x = 0;
...
return (x);
}
f1과 f2는 똑같은 함수처럼 보인지만 반환 타입은 다르다. 첫번째는 int 타입이지만 두번째는 int& 가 된다. 위와 같이 사용하는 경우는 없겠지만 decltype은 조심히 사용해야 함을 잊지 말자.
참고 서적
스콧 마이어스, Effective Modern C++
'C++ > Effective Modern C++' 카테고리의 다른 글
[Effective Modern C++] 항목 6. auto가 원치 않은 형식으로 연역될 때에는 명시적 형식의 초기치를 사용하라 (0) | 2019.09.08 |
---|---|
[Effective Modern C++] 항목 5. 명시적 형식 선언보다는 auto를 선호하라 (0) | 2019.09.08 |
[Effective Modern C++] 항목 4. 연역된 형식을 파악하는 방법을 알아두라 (0) | 2019.09.02 |
[Effective Modern C++] 항목 2. auto의 형식 연역 규칙을 숙지하라 (0) | 2019.08.25 |
[Effective Modern C++] 항목 1. 템플릿 형식 연역 규칙을 숙지하라 (1) | 2019.08.25 |
- Total
- Today
- Yesterday
- Effective Modern C++
- detach
- Join
- Future
- C++11
- Unreal
- MOVE
- std::forward
- Overloading
- async
- 보편 참조
- Forwarding
- C++
- Modern
- 발아시기
- C++14
- CPP
- 포인터
- 람다
- 다이소
- Effective
- thread
- const
- forward
- Override
- C
- std::move
- Perfect
- 보편참조
- auto
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |