gcc only
C++11标准前 类似decltype
功能的运算符
获取目标 *** 作数类型的运算符 返回的是左值 只会涉及基本类型 不包含CV限定符和引用
auto- 对于变量 从它的初始化器推导出它的类型(Since C++11)
- 对于函数 从它的return语句推导出类型(Since C++14)
- 对于非类型模板形参 指定要从实参推导出它的类型(Since C++20)
可配合cv限定符和&
/*
(引用/指针)这样的修饰符一起使用
3条推导规则
- 如果实参是没有括号的标识表达式或类成员访问表达式 那么
decltype
产生以该表达式命名的实体的类型- 如果没有这种实体或该实参指名了一组重载函数 那么程序非良构(即错误的)
- 如果实参是指名某个结构化绑定的没有括号的标识表达式 那么
decltype
产生其被引用类型(Since C++17) - 如果实参是指名某个非类型模板形参的没有括号的标识表达式 那么
decltype
生成该模板形参的类型(当该模板形参以占位符类型声明时,类型会先进行任何所需的类型推导)(Since C++20)
- 如果实参是其他类型为
T
(可以是不完整类型) 的任何表达式- 如果 表达式 的值类别是亡值 将会
decltype->T&&
- 如果 表达式 的值类别是左值 将会
decltype->T&
- 如果 表达式 的值类别是纯右值 将会
decltype->T
- 如果 表达式 是返回类类型纯右值的函数调用 或是右 *** 作数为这种函数调用的逗号表达式 那么不会对该纯右值引入临时量 (Before C++17)
- 如果 表达式 是~~除了(可带括号的)立即调用以外的 (Since C++20)~~纯右值,那么不会从该纯右值实质化临时对象:即这种纯右值没有结果对象。(Since C++17)
- 如果 表达式 的值类别是亡值 将会
- 如果对象的名字带有括号 那么它会被当做通常的左值表达式 从而
decltype(x)
和decltype((x))
通常是不同的类型
对于第一条规则
#include
#include
int main(){
int i = 0;
int* j=&i;
int n[10];
decltype(i=0); // int& // 但不会赋值(Clang)
// rule 1
static_assert(std::is_same_v<decltype(i = 0), int&>);
static_assert(std::is_same_v<decltype(n[5]), int&>);
static_assert(std::is_same_v<decltype(*j), int&>);
static_assert(std::is_same_v<decltype(static_cast<int&&>(i)), int&&>);
static_assert(std::is_same_v<decltype(i++), int>);
static_assert(std::is_same_v<decltype(++i), int&>);
// rule 2
static_assert(std::is_same_v<decltype(std::move(i)), int&&>); // xvalue
static_assert(std::is_same_v<decltype(0, i), int&>); // comma/lvalue
static_assert(std::is_same_v<decltype(i, 0), int>); // rvalue
static_assert(std::is_same_v<decltype("hello world"), const char(&)[12]>); // lvalue
// rule 3
static_assert(std::is_same_v<decltype((i)), int&>);
}
:::tip cv限定符
通常情况下 decltype
会推导出cv限定符
但当表达式是成员变量时 父对象的限定符会被忽略
struct A {
double x;
};
const A* a = new A();
static_assert(std::is_same_v<decltype(a->x),double>);
static_assert(std::is_same_v<decltype((a->x)),const double&>);
但多加一层括号会改变结果
:::
Since C++14
- 只能独立使用(不能搭配cv限定 指针/引用)
- 使
auto
推导使用decltype
方式
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)