使用“自动”types演绎 – 如何找出编译器推断的types?

怎样才能找出编译器在使用auto关键字时推导出的types?

示例1:更简单

 auto tickTime = 0.001; 

这是推断为一个floatdouble?

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

 typedef std::ratio<1, 1> sec; std::chrono::duration<double, sec > timePerTick2{0.001}; auto nextTickTime = std::chrono::high_resolution_clock::now() + timePerTick2; 

nextTickTime是什么types?

我遇到的问题是当我尝试发送nextTickTimestd::cout 。 我得到以下错误:

 ./main.cpp: In function 'int main(int, char**)': ./main.cpp:143:16: error: cannot bind 'std::basic_ostream<char>' lvalue to 'std::basic_ostream<char>&&' std::cout << std::setprecision(12) << nextTickTime << std::endl; // time in seconds ^ In file included from /usr/include/c++/4.8.2/iostream:39:0, from ./main.cpp:10: /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> > >]' operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x) 

我喜欢使用Effective Modern C ++的想法,它使用未实现的模板; 该types是与编译器错误输出:

  template<typename T> struct TD; 

现在对于自动variablesvar ,在定义之后添加:

  TD<decltype(var)> td; 

并为您的编译器观看错误消息,它将包含vartypes。

不需要任何辅助定义的低保技巧是:

 typename decltype(nextTickTime)::_ 

编译器会抱怨_不是nextTickTimetypes的成员。

这是一个使用boost::core::demangle在运行时获取types名称的typeid版本。

 #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; } 

在我的系统上打印这个:

 typeof(i) = int typeof(f) = float typeof(d) = double typeof(s) = std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > typeof(v) = std::vector<int, std::allocator<int> > 

typeid可以用来获取大部分时间的variablestypes。 这是编译器依赖,我看到它给出了奇怪的结果。 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> > > 

正如Daniel Jour所说,阅读错误信息:

 ... _Tp = std::chrono::time_point< std::chrono::_V2::system_clock, std::chrono::duration< double, std::ratio<1l, 1000000000l> > > ... 

低技术解决scheme是将鼠标hover在nextTickTime ,在某些graphics用户界面(GUI)中,将鼠标hover在其他types的设置上.cout nextTickTime之后,select一个合理的值或者函数。

一般来说,如果你知道什么types你使用auto如果你不知道它不使用它。 这有点直观。

所以,如果你知道它的一个interator只是使用auto来减less咒语,如果结果是某种未知的types,你必须在使用auto之前找出它是什么。

另见Herb,Andrei和Scott讨论auto

这个答案给出了一个很好的函数来打印出一个types的名字(实际上是一些实现)。

另外,这个免费的开放源代docker文件库提供了一个打印chrono::duration s值和types的好方法。

把这两个公用事业放在一起:

 #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'; } 

这个输出给我:

 std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<double, std::__1::ratio<1, 1000000000> > > 4.8530542088e+14ns 

编译器推导的types在错误消息中:

 /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 ---------------------------------------------------------------------------------------> 

这是一个复杂的types名称,但它在错误消息中。

作为一个方面说明,要有效地打印出nextTickTime的值,你应该明确地转换成合适的std::chrono::duration并且输出duration::count的结果。

 using std::chrono::duration_cast; using std::chrono::seconds; auto baseTime = ...; std::cout << std::setprecision(12) << duration_cast<seconds>(nextTickTime - baseTime).count() << std::endl; // time in seconds 

这是一种强制编译错误的方法,它显示了tickTime的types:

 struct {} baD = tickTime;