declval — std::declval
declval — std::declval
std::declval은 평가되지 않는 문맥(unevaluated context)에서 타입 T의 참조를 얻는 데 사용하는 함수 템플릿이에요. C++11에서 도입됐어요. <utility> 헤더에 있어요.
실제로 호출되면 안 되고, decltype·sizeof 등에서 표현식의 타입을 알아낼 때만 쓰여요.
출처: cppreference
본문
// <utility> 헤더, C++11 (평가되지 않는 문맥 전용)
template< class T >
typename std::add_rvalue_reference<T>::type declval() noexcept;
declval<T>()은 T의 rvalue 참조를 만들어내는 것처럼 타입만 제공해요. 실제 호출은 불가능하고, 오직 타입 추론에만 사용돼요.
사용 예
#include <utility>
#include <type_traits>
// T에 size()가 있는지, 그 반환 타입은 무엇인지
template<typename T>
using size_type = decltype(std::declval<T>().size());
decltype(std::declval<std::string>().size()) n; // size_type
// 반환 타입 추론
decltype(std::declval<std::vector<int>&>().push_back(1)); // void& (x) 등
declval은 주로 타입 특질(type trait)과 템플릿 메타프로그래밍에서 사용돼요. 기본 생성이 불가능한 타입도 "값이 있다고 치고" 표현식의 타입을 알아낼 수 있어요.
// 기본 생성이 불가능해도 declval로 타입 조사 가능
struct OnlyParam { explicit OnlyParam(int); };
using R = decltype(std::declval<OnlyParam>().~OnlyParam()); // void
// 사실은 declval<OnlyParam&> 로 멤버 접근 등
// 예: 참조하는 멤버의 타입
using ET = decltype(std::declval<std::vector<int>>().emplace_back(1)); // void
주의
declval은 절대 실제로 호출하면 안 돼요 — 정의되지 않은 동작.decltype·sizeof·noexcept·requires같은 평가되지 않는 문맥에서만 사용해요.
std::declval은 타입을 "불러다 쓴 것처럼" 취급해 표현식의 타입·가능성을 컴파일 타임에 조사하는 메타프로그래밍 도구예요.