declval
1. 정의
<utility> 에 정의된 함수 std::declval
컴파일타임 때 타입을 전달하면 해당 타입의 생성자를 직접 호출하지 않더라도 생성된 객체를 나타낼 수 있다
동작을 들어도 잘 이해가 되지 않기 때문에 예제를 참고
2. 예제
문제상황
decltype을 이용해서 특정타입의 특정함수가 반환하는 값을 template으로 명시할 수 있다
이것을 이용해서 들어온 T타입의 f함수를 호출하고 그 결과를 return 하는 함수를 만들어보면 다음과 같다
//T타입의 f함수의 결과 타입을 반환하는 함수
//decltype으로 f()로 명시되어있어서 반환타입을 명시할 수는 있지만
//인자값이 없는 함수만 작동
template <typename T>
decltype(T().f()) call_f_and_return(T& t)
{
return t.f();
}
//인자없는 생성자
struct A
{
int f() { return 0; }
};
//인자있는 생성자
struct B
{
B(int x) {}
int f() { return 0; }
};
int main() {
A a;
B b(1);
call_f_and_return(a); // ok
call_f_and_return(b); // BAD
}
디버그 에러 발생
해당 코드는 에러가 발생한다
T().f()
부분에서 struct A
는 상관이 없지만 struct B
는 인자없는 기본 생성자가 없기 때문에
컴파일 타임 때 실패한다
declval을 통해 해결
#include <utility>
//T타입의 f함수의 결과 타입을 반환하는 함수
template <typename T>
decltype(std::declval<T>().f()) call_f_and_return(T& t)
{
return t.f();
}
//인자없는 생성자
struct A
{
int f() { return 0; }
};
//인자있는 생성자
struct B
{
B(int x) {}
int f() { return 0; }
};
int main() {
A a;
B b(1);
call_f_and_return(a); // ok
call_f_and_return(b); // ok
}
declval을 사용하면 해당 생성자가 없다고 해도 마치 있는 것처럼 작동시킬 수 있다
C++14부터는 더 간단하게 가능
template <typename T>
auto call_f_and_return(T& t)
{
return t.f();
}
하지만 이 이외에 Type Traits에서도 많이 사용됨
댓글남기기