第4章 decltype
说明符(C++11~C++17)
4.1 回顾typeof
和typeid
(1)在C++11标准发布以前,GCC的扩展提供了一个名为typeof
的运算符。通过该运算符可以获取操作数的具体类型。typeof
是GCC所提供,并非C++标准。
int a = 9;
typeof(a) b = 5;
(2)C++标准还提供了一个typeid
运算符来获取与目标操作数类型有关的信息。获取的类型信息会包含在一个类型为std::type_info的对象里。我们可以调用成员函数name获取其类型名,成员函数name返回的类型名在C++标准中并没有明确的规范,所以输出的类型名会因编译器而异。
typeid
并不能像typeof
那样在编译期就确定对象类型
int a = 9;
qDebug() << typeid(a).name(); // msvc输出int GCC输出i
4.2 使用delctype
说明符
(1)语法
int a = 9;
decltype(a) c = 5; // c推断为int
(2)用于函数模板,结合auto
以及后置返回类型,推断返回值类型
C++11之前写法,需要将返回值类型写在typename
中,每次调用都要写明返回值类型
//C++11之前
template <typename R, typename T1, typename T2>
R sum(T1 a1, T2 a2)
{
return a1 + a2;
}
在C++11中使用delctype
,后置返回类型,使用auto
自动推导返回值类型
// C++11
template <typename T1, typename T2>
auto sum(T1 a1, T2 a2) -> decltype(a1 + a2)
{
return a1 + a2;
}
int main()
{
auto x = sum(5, 0.5);
}
在C++14中,支持对函数返回类型的推导,因此就不用decltype
了
// C++14
template <typename T1, typename T2>
auto sum(T1 a1, T2 a2)
{
return a1 + a2;
}
int main()
{
auto x = sum(5, 0.5);
}
4.3 推导规则
decltype(e)
(其中e
的类型为T
)的推导规则有5条。
1.如果e
是一个未加括号的标识符表达式(结构化绑定除外)或者未加括号的类成员访问,则decltype(e)
推断出的类型是e
的类型T。如果并不存在这样的类型,或者e
是一组重载函数,则无法进行推导。
2.如果e
是一个函数调用或者仿函数调用,那么decltype(e)
推断出的类型是其返回值的类型。
3.如果e
是一个类型为T的左值,则decltype(e)
是T&。
4.如果e
是一个类型为T的将亡值,则decltype(e)是T&&
。
5.除去以上情况,则decltype(e)
是T
。
4.4 cv限定符的推导
通常情况下,decltype(e)
所推导的类型会同步e
的cv限定符
当e
是未加括号的成员变量时,父对象表达式的cv限定符会被忽略,不能同步到推导结果。当e
是加括号的数据成员时,父对象表达式的cv限定符会同步到推断结果。
4.5 decltype(auto) 【c++14】
在C++14标准中出现了decltype
和auto
两个关键字的结合体:decltype(auto)
。它的作用简单来说,就是告诉编译器用decltype的推导表达式规则来推导auto
。另外需要注意的是,decltype(auto)
必须单独声明,也就是它不能结合指针、引用以及cv限定符。
使用decltype(auto)
消除返回类型后置的语法
template<class T>
auto return_ref(T& t)
{
return t;
}
int x1 = 0;
static_assert(std::is_reference_v<decltype(returm_ref(x1)));// 编译错误,因为返回值不为引用类型(auto忽略cv限定符),导致static_assert在编译期报错
template<class T>
auto return_ref(T& t) -> delctype(t)
{
return t;
}
int x1 = 0;
static_assert(std::is_reference_v<decltype(returm_ref(x1)));// 编译成功
template<class T>
delctype(auto) return_ref(T& t)
{
return t;
}
int x1 = 0;
static_assert(std::is_reference_v<decltype(returm_ref(x1)));// 编译成功
4.6 decltype(auto)作为非类型模板形参占位符 【c++17】
在C++17标准中decltype(auto)
也能作为非类型模板形参的占位符,其推导规则和上面介绍的保持一致
template <decltype(auto) N>
void f()
{
qDebug() << N;
}
static const int x = 11;
static int y = 7;
int main(int argc, char *argv[])
{
f<x>(); // 正确
f<(x)>(); // 正确
// f<y>(); // y不是编译期常量,编译报错
f<(y)>(); // (y)是表达式,表达式的值是编译期常量
}
标签:11,decltype,int,auto,C++,说明符,类型,return
From: https://www.cnblogs.com/Danieeel959/p/18391965