使用“自动”types演绎 – 如何找出编译器推断的types?
怎样才能找出编译器在使用auto
关键字时推导出的types?
示例1:更简单
auto tickTime = 0.001;
这是推断为一个float
或double?
例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?
我遇到的问题是当我尝试发送nextTickTime
到std::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;
并为您的编译器观看错误消息,它将包含var
types。
不需要任何辅助定义的低保技巧是:
typename decltype(nextTickTime)::_
编译器会抱怨_
不是nextTickTime
types的成员。
这是一个使用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;