查看自动类型推导结果的方法

这篇具有很好参考价值的文章主要介绍了查看自动类型推导结果的方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在《深入解析C++的auto自动类型推导》和《深入解析decltype和decltype(auto)》两篇文章中介绍了使用auto和decltype以及decltype和auto结合来自动推导类型的推导规则和用法,虽然确定类型的事情交给编译器去做了,但是在有的时候我们可能还是想知道编译器推导出来的类型具体是什么,下面就来介绍几种获取类型推导结果的方法,根据开发的不同阶段,你可以在不同阶段采用不同的方法,比如在编写代码时,编译代码时,代码运行时。

利用IDE查看

当你在编写代码的过程中想查看一下某个变量推导出来的类型是什么,做到心中有数,其实在IDE中就可以直接查看,现在的IDE都比较智能,如微软的Visual Studio和目前比较流行的跨平台编辑器VS Code都有此功能。你只要将鼠标移到想要查看的那个变量上面,就会弹出这个变量的类型,不过要让IDE能够推导出代码中变量的类型,你的代码至少要没有语法错误,因为IDE会静态分析你代码来推导出这些类型,如下面的代码:

int a;
auto x = a;
auto& y = a;

你把鼠标移动x上面,则会弹出显示“int x”,把鼠标移动y上面,就会弹出显示“int& y”。对于C++的内置类型,IDE基本上都能推导出来,但是遇到比较复杂的类型或者复杂的代码上下文中,IDE可能就有点不够智能了。

借助工具查看

当IDE不能正确显示出变量的类型的时候还可以选择借助外部的工具来查看,这里推荐一个在线工具,地址是:https://cppinsights.io,这是一个基于Clang的工具,对用户所写的C++代码转换成最终形式的C++代码,有点类似于C/C++的预处理器一样,把一些宏代码替换成真实的代码一样,但它的功能更进一步也更强大,该工具支持基于范围的循环、结构化绑定、生成默认构造函数、初始化列表、auto与decltype转换成真实类型,最强大的是会生成模板实例化后的代码,这些功能对于调试C++代码非常有用。使用的界面如下:

查看自动类型推导结果的方法

(点击查看大图)

左边是我们输入的原始代码,输入结束之后点击左上角的三角形按钮,就会生成右边经过转换后的代码,可以看到右边中已经将类型别名T1到T10等的类型转换成具体的类型了,使用时可以在上面的下拉列表框中选择不同的C++标准。

需要注意的是,这个工具我发现了一个Bug,就是上面代码中的T9类型别名,正确的类型应该是func函数的类型:int(int, int),这里显示为它的返回值的类型了。

编译时打印

编译器肯定是知道变量的类型的,但是它没法直接告诉你,有一个可以让编译器告诉你的办法,就是编译发生错误时编译器在报告的错误信息中肯定会提到导致此错误的类型,因此我们可以声明一个如下的模板:

template<typename T>
class dumpType;

因为上面的模板只有声明,没有具体的定义,因此如果要实例化这个模板就会导致一个编译错误。所以我们想要查看哪个变量的类型,只要将这个变量的类型作为模板的形参去实例化它,就会导致一个错误,在编译器给出的错误信息里就会显示出这个变量的具体类型,如下所示:

const int x1 = 1;
auto j = x1;
dumpType<decltype(j)>{};

编译时发生错误,其中输出的错误信息含有这一行:

error: implicit instantiation of undefined template 'dumpType<int>'

dumpType中尖括号内的int就是j的类型了,以此类推,只要将想要查看的变量替换到上面的参数中就可以了。但是这里有一个缺点,就是每次只能查看一个变量的类型,需要查看多个变量时就显得繁琐。好在C++11标准引入了支持可变参数的模板特性,我们可以利用这个特性来完善上面的功能,将上面的模板修改一下:

template<typename... Ts>
class dumpType;

现在可以一次传递多个参数给此模板,如下面的例子:

template<typename... Ts>
class dumpType;

int func(int, int) {
    int x;
    return x;
}

class Base {
public:
    int x = 0;
};

int main() {
    const Base b;
    const int ci = 1;
    auto x = ci;
    using T1 = decltype(x);
    using T2 = decltype((x));
    using T3 = decltype(b.x);
    using T4 = decltype((b.x));
    using T5 = decltype(func);
    dumpType<T1, T2, T3, T4, T5>{};
}

编译时将输出以下的错误信息:

error: implicit instantiation of undefined template 
'dumpType<int, int &, int, const int &, int (int, int)>'

运行时输出

有时我们想要在代码运行的时候输出某些变量的类型,这时候可以借助C++的RTTI特性,C++标准库提供了typeid函数和type_info类,对变量或者类型调用typeid会返回一个type_info对象,type_info类里有一个成员函数name,这个函数返回一个const char*类型的名称,但这个名称一般都经过C++的混淆,比较不易看懂,如以下的代码:

auto add (auto p1, auto p2) { return p1 + p2; };
auto d = add(1, 2.0);
printf("type of d is %s\n", typeid(d).name());
auto s = add("hello"s, "world"s);
printf("type of s is %s\n", typeid(s).name());

输出的结果是:

type of d is d
type of s is NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE

输出结果中的d代表的是double类型,如int类型的话则显示i,std::string类型的原型比较复杂,所以输出来的结果比较难看懂。但这种方法最大的缺点是功能不太完善,比如对于引用类型它无法正确的显示出来,比如下面的代码:

int i = 1;
auto& j = i;
printf("type of j is %s\n", typeid(j).name());

变量j正确的类型应该是int&,但是上面的输出结果是i,是int类型,估计是j作为参数传给typeid函数的时候是作为值传递的,丢失了引用属性,在这里CV修饰词也会被忽略掉,如在上面定义变量j时加上const修饰,但输出结果还是int类型。

这时可以采用另外一种手段来输出变量的类型,跟上小节中的例子一样借助模板的技术,实现一个模板函数,在模板函数中利用编译器提供的宏,把这个函数的原型打印出来,函数原型中就包含了函数的参数个数及其类型,这个宏由于不是C++标准中定义的,是由各编译器扩展的,因此名称不一样,在GCC/Clang中是__PRETTY_FUNCTION__,在微软的MSVC中是__FUNCSIG__,如下代码:

#include <iostream>

template<typename... Ts>
void dumpType() {
    // GCC/Clang使用这行
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    // MSVC则使用下面这行
    //std::cout << __FUNCSIG__ << std::endl;
};

int func(int, int) {
    int x;
    return x;
}

class Base {
public:
    int x = 0;
};

int main() {
    const Base b;
    const int ci = 1;
    auto x = ci;
    using T1 = decltype(x);
    using T2 = decltype((x));
    using T3 = decltype(b.x);
    using T4 = decltype((b.x));
    using T5 = decltype(func);
    dumpType<T1, T2, T3, T4, T5>();
}

各个编译器输出的结果是:

// Clang
void dumpType() [Ts = <int, int &, int, const int &, int (int, int)>]
// GCC
void dumpType() [with Ts = {int, int&, int, const int&, int(int, int)}]
// MSVC
void __cdecl dumpType<int,int&,int,const int&,int(int,int)>(void)

此篇文章同步发布于我的微信公众号:查看自动类型推导结果的方法

如果您感兴趣这方面的内容,请在微信上搜索公众号iShare爱分享或者微信号iTechShare并关注,或者扫描以下二维码关注,以便在内容更新时直接向您推送。
查看自动类型推导结果的方法文章来源地址https://www.toymoban.com/news/detail-849940.html

到了这里,关于查看自动类型推导结果的方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • pycharm如何查看之前的运行结果

    谁能懂用pycharm跑了一夜的代码,早上起来,电脑突然关机了!!!!!!!!!!气死我了!!!! 不过正是因为遇到的一个又一个的问题,才能探索未知的东西,就比如昨天某位小李同学,让我做PPT的放大镜效果,嘿,这学习机会不就来了吗,贵宾们是否也想知道放大镜

    2024年02月02日
    浏览(38)
  • 三、yolov8训练结果查看和模型预测

    1、在模型训练结束后,如下图所示,找到该文件夹。 2、然后找到weights文件夹中的best.pt文件,这就是该数据训练后的模型。 1、在assets文件夹下创建FPC-2文件夹,放入一些同类FPC预测结果。 2、和训练同级文件夹,找到predict.py文件,即为模型预测文件。 3、修改model路径,修改

    2024年01月23日
    浏览(50)
  • Linux查看进程PID的方法(linux查进程的pid)附带自动kill 掉

    Linux查看进程PID的方法 Linux作为一款多用户、多任务的操作系统,可以同时处理多个任务,每个任务的执行都由进程来实现。在每个进程执行的过程中,都会有一个唯一标识符,即称为PID(Process Identifier)进程ID。Linux系统有很多命令用来查看进程PID,下面介绍几种常用的查看

    2024年02月01日
    浏览(91)
  • 【c++入门】引用详解 | auto的类型推导 | 范围for循环 | nullptr空指针

    🎥 屿小夏 : 个人主页 🔥个人专栏 : C++入门到进阶 🌄 莫道桑榆晚,为霞尚满天! 上篇文章中,对函数重载和内联函数的作用和特性使用,进行了精细的详解。 引用和指针混不清?引用的抽丝剥茧!还有不用写类型可以自动推导的?for遍历竟然还有我们没见过的面

    2024年02月06日
    浏览(139)
  • CST学习:CST Design Suite中S参数仿真结果查看及把仿真结果添加到结果文件夹下

    1.S参数顺利完成仿真后,Messages窗口会有显示 2. 在NT的Task的SPara1下会有仿真结果 3.打开S-Param,界面跟CST微波工作室 一样,设置也一样,这里不再过多赘述 4.下面我们把仿真结果添加到Results文件夹下 。右键单击Results,点击Add... 5.刚新建会首先让您命名结果文件夹,这里采用默认

    2024年02月15日
    浏览(45)
  • YOLOv5 使用tensorboard查看可视化训练结果

    1.1.找的models/yolo.py文件中,将最下面有关 Tensorboard 的注释打开 2.进入项目根目录 比如你训练的是第20个版本,那么 tensorboard --logdir=./runs/train/exp20 就可以查看当前训练的可视化结果了 3.通过浏览器查看可视化训练结果

    2024年02月16日
    浏览(51)
  • 【c++速通】入门级攻略:引用详解 | auto的类型推导 | 不一样的for循环 | nullptr版本空指针

    🎥 屿小夏 : 个人主页 🔥个人专栏 : C++入门到进阶 🌄 莫道桑榆晚,为霞尚满天! 上篇文章中,对函数重载和内联函数的作用和特性使用,进行了精细的详解。 引用和指针混不清?引用的抽丝剥茧!还有不用写类型可以自动推导的?for遍历竟然还有我们没见过的面

    2024年02月08日
    浏览(46)
  • js数据类型和六种运算结果为false的情况

    number:数字(整数、小数、NaN(Not a Number)) string:字符串、单双引皆可 boolean:布尔。true、false null:对象为空 undefined:当声明的变量初始化时,该变量的默认值是undefined 需要注意以下两点: (1) NaN也是number类型; (2) null类型的数据,返回值是object; js语法的松散,通过

    2024年02月06日
    浏览(25)
  • 浅谈PHP框架中类成员方法的类类型形参是怎么利用ReflectionClass反射类自动实例化的(应该是全网首发)

    1. 或许是全网首发,我翻过很多文章,从未有一个博主讲过这个东西,很多博主只讲了IOC、DI和反射机制的常见用法,因类类型形参反射的巧妙用法有相当高的难度和学习盲区,所以从未有人讲过类类型的形参它怎么就被自动实例化的。 2. 在Laravel框架,或者是其它框架中,类

    2024年02月06日
    浏览(48)
  • 【应试技巧】格林公式记忆方法及简单推导

    视频讲解:格林公式记忆方法及简单推导 大家在学格林公式的时候会发现其实书本上给的形式并不容易记忆。 大家可能会产生下述的问题 忘记了逆时针和顺时针哪个是正方向? 忘记了P,Q该对谁求偏导? 忘记了求偏导以后是谁减谁? 本文分为两个部分,第一部分是将格林

    2024年02月05日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包