前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >decltype 使用

decltype 使用

作者头像
全栈程序员站长
发布2022-09-30 18:42:20
3740
发布2022-09-30 18:42:20
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

功能

  • decltype可以将给定的表达式或变量的类型推导出来,包含引用和指针。
  • 一般用于复杂表达式作为返回值的类型推导。
  • 可以用于补足c++11auto缺陷.
  • 编译阶段的事情,不会任何执行,表达式也不会执行。

类型规则

  • 规则一:声明类型,类型包含引用就有引用,没有引用也不会自行添加。
  • 规则二:返回值则根据返回值类型确定最终类型。
  • 规则三:表达式根据默认和重载得到的最终类型。不建议特别复杂的表达式。

声明类型分析

案例一 int main() { int a = 0; decltype(a) b; b.error(); }

  • 最终bint类型.

案例二 #include <cassert> int main() { const int & a = 0; decltype(a) b = a; assert(&b == &a); }

  • 通过执行知道,ba是一个地址,是引用.
  • 而且类型基本类型也一致,所以类型是一致的.

案例三

代码语言:javascript
复制
#include<iostream>
class T { 
         
public:
   T() { 
          std::cout << "s"  << this << std::endl; }
   ~T() { 
          std::cout << "e" << this << std::endl; }
};
int main() { 
         
   const T && a = T();
   decltype(a) b = T();
   return 0;
}
 

  • 只进行了两次的构造.

返回值推测

案例一 #include<vector> #include<iostream> template <typename T,typename I> auto show(T&& a, I i) -> decltype(a[i]) { std::cout << "cool" << std::endl; return std::forward<T>(a[i]); } int main() { std::vector<int> s = { 1,2,3,4 }; decltype(show("123", 1)) a = 2; return 0; }

  • 这里就是,但是不会执行std::cout,因为并不会执行,在编译阶段确定了类型而已.

案例二 #include<vector> int main() { std::vector<int> s = { 1,2,3,4 }; decltype(s[1]) a; return 0; }

  • vector进行索引返回的是引用,引用类型必须初始化,所以报错。

复杂表达式

案例一 int main() { decltype((1+2+3+4)) a = 1; return 0; }

  • 结果是int类型.

案例二 int main() { int a = 1; decltype((a)) b = 1; return 0; }

  • 对变量进行(var)操作得到的是对应的引用类型,C++11的新特性.
  • 所以这里编译报错.

decltype的真正作用

组合后的返回值,复杂表达式。 说明

  • std::vector进行[],返回的一般都是&类型,但是bool则例外.
  • 那么对于下面的代码,则不严谨.

简单代码 template <typename T,typename I> auto show(T& a, I i) ->decltype(a[i]) { return a[i]; }

  • 不好看.

好看点 template <typename T,typename I> auto show(T& a, I i) { return a[i]; }

  • C++14才支持,而且有点小问题.
  • 提示,auto推导,C++11仅仅支持简单的单个表达式推导,不支持复杂的组合表达式.
  • 但是C++14支持,C++14这里正常编译.
  • 但是auto不支持引用类型推导.这里是基本类型,是个右值。

支持引用 template <typename T,typename I> decltype(auto) show(T& a, I i) { return a[i]; }

  • auto表示类型推导,decltype表示按照decltype的规则进行,即何在一起就是支持引用类型推导。
  • 美中不足就是,这里仅仅支持了左值。虽然加一个const就可以支持右值,但是又不是这里讨论的手段,因为无法区分是操作的左值还是右值。
  • 操作左值和操作右值的意义是完全不一样的。 支持右值引用 template <typename T,typename I> decltype(auto) show(T&& a, I i) { return a[i]; }
  • 支持右值,但是这里的a是左值,非匿名消亡值.
  • a[i]返回引用,show执行完就消亡,那么会导致引用悬空.

完善最终版 template <typename T,typename I> decltype(auto) show(T&& a, I i) { return std::forward<T>(a)[i]; }

  • 转化为对应类型,调用对应类型的重载。然后左值返回引用,右值返回右值变量。

void show() && { } void show() &{ } 不同修饰调用不同的函数

  • 函数名后面可以用修饰变量的修饰符修饰,&&,const,volatile,&,也可以任意组合.
  • 这些可以重载,调用会使用最匹配的版本.
  • 使用了修饰的就不能定义无修饰的版本. 即show()&就不能定义show()这种.
  • 不同修饰的可以根据语义返回不同的对象.这些函数的函数名也不一样.

C++11

  • ()
    • 对一个变量加(),得到的是一个引用类型.
  • 注意
    • 返回值的时候用这种,可能会带来引用悬空的情况.

总结

  • decltype得到的是声明的类型.
  • 复杂表达式得到的是最终结果的类型,即运算后结果的声明类型.
  • C++14允许decltype(auto)组合完美的推测.C++11可以通过后置的方式达到同样的效果.C++14更加简洁.

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/195527.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年9月9日 下,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 功能
  • 类型规则
  • 声明类型分析
  • 返回值推测
  • 复杂表达式
  • decltype的真正作用
  • C++11
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档