C++ 使用';自动';类型推断-如何找出编译器推断的类型?

C++ 使用';自动';类型推断-如何找出编译器推断的类型?,c++,c++11,auto,chrono,C++,C++11,Auto,Chrono,使用auto关键字时,如何找出编译器推导出的类型 示例1:更简单 auto tickTime = 0.001; 是否将其推断为浮动或双精度? 例2:更复杂(以及我目前的头痛): typeid在大多数情况下可用于获取变量的类型。它依赖于编译器,我看到它给出了奇怪的结果。默认情况下,g++已启用RTTI,但在Windows端不确定 #include <iostream> #include <typeinfo> #include <stdint.h> #inclu

使用
auto
关键字时,如何找出编译器推导出的类型

示例1:更简单

auto tickTime = 0.001;
是否将其推断为
浮动
双精度?

例2:更复杂(以及我目前的头痛):


typeid在大多数情况下可用于获取变量的类型。它依赖于编译器,我看到它给出了奇怪的结果。默认情况下,g++已启用RTTI,但在Windows端不确定

#include <iostream>
#include <typeinfo>
#include <stdint.h>
#include <chrono>
#include <ctime>

typedef std::ratio<1, 1> sec;
int main()
{
    auto tickTime = .001;
    std::chrono::duration<double, sec > timePerTick2{0.001};
    auto nextTickTime = std::chrono::high_resolution_clock::now() + timePerTick2;
    std::cout << typeid(tickTime).name() << std::endl;
    std::cout << typeid(nextTickTime).name() << std::endl;

    return 0;
}

./a.out | c++filt

double
std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > >
#包括
#包括
#包括
#包括
#包括
类型定义标准::比率秒;
int main()
{
自动滴答时间=.001;
std::chrono::duration timePerTick2{0.001};
auto nextTickTime=std::chrono::高分辨率时钟::now()+timePerTick2;
STD::CUT< P>我喜欢使用有效的现代C++中的思想,它使用未实现的模板;类型是用编译器错误输出的:

 template<typename T> struct TD;

并观察编译器的错误消息,它将包含
var

类型作为旁注,要有效地打印出
nextTickTime
中的值,您应该显式转换为合适的值并输出结果

使用std::chrono::duration\u cast;
使用std::chrono::seconds;
自动基准时间=。。。;

std::cout这里有一个
typeid
版本,它使用
boost::core::demangle
在运行时获取类型名

#include <string>
#include <iostream>
#include <typeinfo>
#include <vector>
using namespace std::literals;

#include <boost/core/demangle.hpp>

template<typename T>
std::string type_str(){ return boost::core::demangle(typeid(T).name()); }

auto main() -> int{
    auto make_vector = [](auto head, auto ... tail) -> std::vector<decltype(head)>{
        return {head, tail...};
    };

    auto i = 1;
    auto f = 1.f;
    auto d = 1.0;
    auto s = "1.0"s;
    auto v = make_vector(1, 2, 3, 4, 5);

    std::cout
    << "typeof(i) = " << type_str<decltype(i)>() << '\n'
    << "typeof(f) = " << type_str<decltype(f)>() << '\n'
    << "typeof(d) = " << type_str<decltype(d)>() << '\n'
    << "typeof(s) = " << type_str<decltype(s)>() << '\n'
    << "typeof(v) = " << type_str<decltype(v)>() << '\n'
    << std::endl;
}
#包括
#包括
#包括
#包括
使用名称空间std::literals;
#包括
模板
std::string type_str(){return boost::core::demangle(typeid(T).name());}
auto main()->int{
自动生成向量=[](自动头部、自动…尾部)->标准::向量{
返回{head,tail…};
};
自动i=1;
自动f=1.f;
自动d=1.0;
自动s=“1.0”s;
自动v=生成向量(1,2,3,4,5);
标准::cout

一种低技术的解决方案是将鼠标悬停在
nextTickTime
上,在某些GUI中,它在
cout
中的
nextTickTime
之后为type else设置一个
,并选择一个合理的外观值或函数

一般来说,如果你知道你使用的是哪种类型,请使用
auto
如果你不知道,请不要使用它。这有点违反直觉

因此,如果你知道它是一个互动器,只需使用“自动”来减少咒语,如果结果是某种未知的类型,你必须在使用
auto
之前找出它是什么

另请参见

提供了一个很好的打印类型名称的功能(实际上有两个实现)

此外,这为打印
chrono::duration
s的值和类型提供了一种很好的方法

将这两个实用程序放在一起:

#include "chrono_io.h"
#include "type_name.h"
#include <iomanip>
#include <iostream>

int
main()
{
    using namespace date;
    typedef std::ratio<1, 1> sec;
    std::chrono::duration<double, sec > timePerTick2{0.001};
    auto nextTickTime = std::chrono::high_resolution_clock::now() + timePerTick2;
    std::cout << type_name<decltype(nextTickTime)>() << '\n';
    std::cout << std::setprecision(12) << nextTickTime.time_since_epoch() << '\n';
}
#包括“chrono_io.h”
#包括“type_name.h”
#包括
#包括
int
main()
{
使用名称空间日期;
类型定义标准::比率秒;
std::chrono::duration timePerTick2{0.001};
auto nextTickTime=std::chrono::高分辨率时钟::now()+timePerTick2;
std::cout如前所述,阅读错误消息:

... _Tp = std::chrono::time_point<
           std::chrono::_V2::system_clock,
           std::chrono::duration<
             double, std::ratio<1l, 1000000000l> > > ...
/usr/include/c++/4.8.2/ostream:602:5: error:   initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>;
 _Tp = std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<double, std::ratio<1l, 1000000000l> > >]’
  ^^   <-------- the long type name --------------------------------------------------------------------------------------->
…\u Tp=std::chrono::time\u点<
标准:时钟::_V2::系统时钟,
标准::计时::持续时间<
双精度,标准::比率>>。。。

一个不需要任何先前助手定义的低保真技巧是:

typename decltype(nextTickTime)::_

编译器会抱怨
\uu
不是
nextTickTime
的任何类型的成员。

这里有一种强制编译错误的方法,显示
tickTime
的类型:

struct {} baD = tickTime;

编译器推断的类型在错误消息中:

... _Tp = std::chrono::time_point<
           std::chrono::_V2::system_clock,
           std::chrono::duration<
             double, std::ratio<1l, 1000000000l> > > ...
/usr/include/c++/4.8.2/ostream:602:5: error:   initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>;
 _Tp = std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<double, std::ratio<1l, 1000000000l> > >]’
  ^^   <-------- the long type name --------------------------------------------------------------------------------------->
/usr/include/c++/4.8.2/ostream:602:5:错误:初始化'std::basic_ostream&std::operator@jonathan oconnor的参数1,您可以使用c++14中引入的属性生成非常干净的解决方案:

模板
[[deprecated]]constexpr void打印类型(T const&){

不幸的是,MSVC发出的诊断没有提到类型。()

当有疑问时,我会作弊。制作一个便宜的黑客程序,声明自动变量但不使用它,然后检查调试器认为它是什么。我使用
eclipse IDE
,大多数时候我只是将鼠标悬停在
auto
关键字上,然后弹出推断的类型。在任何IDE中工作的最可靠的黑客程序-只是不使用
auto
:)说真的,如果你真的关心到底是哪种类型推导出来的,为什么你会使用
auto
,在不同的情况下会产生不同的类型?嗯……我遗漏了什么?它就在错误消息中?关于
auto tickTime=0.001;
:文字是一个很好的,非常聪明的文字!是
吗>模板void td(T);
也适用于自动变量var?@ratchetfreak是的,但随后会出现链接器错误而不是编译错误。前面显示了编译错误。参考“Windows端”没有多大意义。GCC在Windows上工作,其他流行的编译器也是如此,所以我假设您指的是Microsoft的编译器。事实上,MSVC默认情况下也会启用RTTI。您必须使用
/GR-
显式关闭它。如果您在使用<代码> /GR- < /代码>,因此问题将是非常明显的。(当然,任何C++编译器都必须默认有RTTI,否则,它将完全违反语言标准。)@CodyGray:编译器的默认设置不符合标准是很常见的。如果你想要一个符合标准的编译器,你通常需要添加一些选项。我的经验表明,编译器的默认选项放松标准遵从性,但禁用基本语言功能(如RT)是比较常见的TI或异常似乎太远了。我还没有看到一个正常的(即非嵌入式或其他特殊用例)编译器能够立即禁用这两种功能。@Martin此代码不使用RTTI。这些表达式的运行时类型在编译时是静态已知的,它们
... _Tp = std::chrono::time_point<
           std::chrono::_V2::system_clock,
           std::chrono::duration<
             double, std::ratio<1l, 1000000000l> > > ...
typename decltype(nextTickTime)::_
struct {} baD = tickTime;
/usr/include/c++/4.8.2/ostream:602:5: error:   initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>;
 _Tp = std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<double, std::ratio<1l, 1000000000l> > >]’
  ^^   <-------- the long type name --------------------------------------------------------------------------------------->