decltype는 주어진 이름이나 표현식의 형식을 알려준다.
대부분 다음과같이 예측한 대로 형식을 말해준다.
const int i = 0; // decltype(i) : const int
bool f(const Widget& w); // decltype(w) : const Widget&
// decltype(f) : bool(const Widget&)
struct Point { // decltype(Point::x) : int
int x, y; // decltype(Point::y) : int
};
Widget w; // decltype(w) : Widget
if(f(w)); // decltype(f(w)) : bool
template<typename T>
class vector {
public:
...
T& operator[] (std::size_t index);
};
vector<int> v; // decltype(v)는 vector<int>
...
if(v[0] == 0) ... // decltype(v[0])은 int&
c++11에서 decltype은 다음과같이 함수의 반환 형식이 그 매개변수 형식들에 의존하는 함수 템플릿을 선언할 때 주로 사용한다.
template<typename Container, typename Index>
auto authAndAccess(Container& c, Index i)
->decltype(c[i])
{
authenticateUser();
return c[i];
}
형식 T를 담은 컨테이너들에 대한 operator[]연산은 일반적으로 T&을 돌려주지만 std::vector<bool>은
완전히 새로운 객체(T) 를 돌려주기 때문에 이렇게 써주는 것이 좋다. --> 그런데 그건 그냥 c[i]를 반환해도 T를 돌려주지 않나요..
c++11에서는 위와같이 함수 이름 앞에 auto를 써주는 것은 형식 연역과는 아무 상관이 없다.
단지 후행반환 형식, 즉 이자리가 아니라 매개변수 목록 다음에 반환 형식을 선언 하겠다는 것을 나타내는 것이다.
이 방식의 장점은 매개변수들을 이용해서 반환형식을 지정할 수 있다 것이다.
하지만 c++14에서는 반환형식 연역을 허용한다.
c++11은 람다함수가 한문장으로 이루어져있다면 반환형식의 연역을 허용하고,
c++14에서는 모든 람다와 모든 함수의 반환형식 연역을 허용한다.
이때 c++14에서 다음과 같은 상황이 발생한다.
template<typename Container, typename Index>
auto authAndAccess(container& c, Index i)
{
authAndAccess(Container& c, Index i)
return c[i];
}
위와같이 선언 했을 때, c[i]의 형식은 &c[i] 이지만, auto의 형식 연역 방식에 따라 c[i]를 돌려주게 된다.
따라서 이를 막기 위해 다음과 같이 선언 한다.
template<typename Container, typename Index>
decltype(auto) authAndAccess(container& c, Index i)
{
authAndAccess(Container& c, Index i)
return c[i];
}
이 외에도 auto에 의해 &가 생략되는 모든 곳에 &가 생략되지 않게 하기 위해 쓸 수 있다.
이 다음 부분은 나중에 이해할 수 있을 때 다시 보고 정리하겠다..