第2.11章: decltype(T)
什么是 decltype?
decltype 关键字检查表达式的类型并产出该类型。
与从初始化器推导的 auto 不同,decltype 在不创建对象的情况下给出表达式的精确类型。
基础示例
#include <cstddef>
::std::size_t x{42zu};
decltype(x) a{100zu}; // a has type ::std::size_t
decltype(42zu) b{200zu}; // b has type ::std::size_t
decltype(x + 1) c{300zu}; // c has type ::std::size_t
decltype 取圆括号内表达式的类型,并用它来做声明。
与 auto 的区别
auto从初始化器推导类型。decltype检查表达式的类型,即使没有初始化也可以。auto可能会调整类型(例如剥离引用),而decltype会精确保留它们。
配合 decltype 的引用
#include <cstddef>
::std::size_t y{500zu};
::std::size_t& ry{y};
decltype(ry) d{y}; // d has type ::std::size_t& (reference)
decltype 保留引用类型。如果表达式是引用,声明的对象也会是引用。
配合 decltype 的 const
#include <cstddef>
::std::size_t const z{600zu};
decltype(z) e{700zu}; // e has type ::std::size_t const
decltype 也会保留被检查表达式上的 const 限定符。
⚠️ 小心:decltype(x) vs decltype((x))
#include <cstddef>
::std::size_t v{800zu};
decltype(v) a{900zu}; // a has type ::std::size_t
decltype((v)) b{v}; // b has type ::std::size_t& (reference)
这一差异来自 decltype 规则对表达式的处理方式:
decltype(x)—— 当对象的名字不带括号出现时,类型就是该对象的声明类型(此处是::std::size_t)。decltype((x))—— 当表达式被括号包裹时,它被当作左值表达式。 类型变为T&(此处是::std::size_t&)。
简而言之:decltype(x) 给出声明类型,而 decltype((x)) 给出引用类型,因为表达式 (x) 是一个左值。
要点
decltype产出表达式的类型。- 与
auto不同,它不需要初始化器。 decltype保留引用与const限定符。decltype(x)是x的声明类型。decltype((x))是引用类型,因为(x)是左值表达式。