Wie kann ich herausfinden, welchen Typ der Compiler bei Verwendung des auto
Schlüsselworts abgeleitet hat?
Beispiel 1: Einfacher
auto tickTime = 0.001;
Wurde dies als float
oder oder abgeleitet?double?
Beispiel 2: Komplexer (und meine gegenwärtigen Kopfschmerzen):
typedef std::ratio<1, 1> sec;
std::chrono::duration<double, sec > timePerTick2{0.001};
auto nextTickTime = std::chrono::high_resolution_clock::now() + timePerTick2;
Welcher Typ ist nextTickTime
?
Das Problem , das ich habe, ist , wenn ich versuche zu senden nextTickTime
an std::cout
. Ich erhalte folgende Fehlermeldung:
./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)
eclipse IDE
und die meiste Zeit bewege ich einfach die Maus über dasauto
Schlüsselwort und der abgeleitete Typ erscheint.auto
:) Im Ernst, wenn Sie sich wirklich Gedanken darüber machen, welcher Typ genau abgeleitet wurde, warum sollten Sie dann einen verwenden,auto
der unter verschiedenen Umständen zu einem anderen Typ führen kann?auto tickTime = 0.001;
: ohnef
das wörtliche ist ein doubleAntworten:
Ich verwende gerne Ideen aus Effective Modern C ++, die nicht implementierte Vorlagen verwenden. Der Typ wird mit einem Compilerfehler ausgegeben:
template<typename T> struct TD;
Fügen Sie nun für die automatische Variable
var
nach ihrer Definition Folgendes hinzu:TD<decltype(var)> td;
Und sehen Sie sich die Fehlermeldung für Ihren Compiler an, sie enthält den Typ
var
.quelle
template<typename T> void td(T t);
auch für die auto variable var funktionieren?Ein Lo-Fi-Trick, für den keine vorherigen Hilfsdefinitionen erforderlich sind, ist:
typename decltype(nextTickTime)::_
Der Compiler wird sich beschweren, dass er
_
kein Mitglied eines beliebigen TypsnextTickTime
ist.quelle
Hier ist eine
typeid
Version, mitboost::core::demangle
der der Typname zur Laufzeit abgerufen wird.#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; }
Welches druckt dies auf meinem System:
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> >
quelle
Mit typeid kann meistens der Variablentyp abgerufen werden. Es ist vom Compiler abhängig und ich habe gesehen, dass es seltsame Ergebnisse liefert. In g ++ ist RTTI standardmäßig aktiviert, auf der Windows-Seite nicht sicher.
#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> > >
quelle
/GR-
. Sie erhalten einebad_typeid
Ausnahme, wenn Sie versuchen,typeid
beim Kompilieren mit zu verwenden/GR-
, sodass das Problem offensichtlich ist. (Natürlich müsste jeder C ++ - Compiler standardmäßig RTTI aktiviert haben, da dies sonst einen völligen Verstoß gegen den Sprachstandard darstellt.)Wie Daniel Jour sagte, lesen Sie die Fehlermeldung:
... _Tp = std::chrono::time_point< std::chrono::_V2::system_clock, std::chrono::duration< double, std::ratio<1l, 1000000000l> > > ...
quelle
Eine Low-Tech-Lösung ist das Bewegen des Mauszeigers, über
nextTickTime
den in einigen GUIs der Typ "else.
after"nextTickTime
in "a" gesetzt wird,cout
und ein angemessen aussehender Wert oder eine Funktion ausgewählt.Wenn Sie wissen, welchen Typ Sie verwenden,
auto
wenn Sie ihn nicht kennen , verwenden Sie ihn im Allgemeinen nicht. Welches ist ein bisschen kontraintuitiv.Wenn Sie also wissen, dass es sich um einen Interator handelt, verwenden Sie einfach auto, um die Beschwörungsformeln zu reduzieren. Wenn das Ergebnis ein unbekannter Typ ist, müssen Sie vor der Verwendung herausfinden, um was es sich handelt
auto
.Siehe auch Herb, Andrei und Scott
auto
quelle
Diese SO-Antwort bietet eine nette Funktion zum Ausdrucken des Namens eines Typs (tatsächlich einige Implementierungen).
Darüber hinaus bietet diese kostenlose Open-Source-Bibliothek nur für Header eine gute Möglichkeit, den Wert und den Typ von
chrono::duration
s auszudrucken .Zusammenfügen dieser beiden Dienstprogramme:
#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'; }
Diese Ausgabe für mich:
std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<double, std::__1::ratio<1, 1000000000> > > 4.8530542088e+14ns
quelle
Der vom Compiler abgeleitete Typ steht in der Fehlermeldung:
/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 --------------------------------------------------------------------------------------->
Es ist ein komplizierter Typname, der jedoch in der Fehlermeldung enthalten ist.
quelle
Um den Wert in effektiv auszudrucken,
nextTickTime
sollten Sie explizit in einen geeigneten Wert konvertierenstd::chrono::duration
und das Ergebnis von ausgebenduration::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
quelle
Hier ist eine Möglichkeit, einen Kompilierungsfehler zu erzwingen, der den Typ von
tickTime
:struct {} baD = tickTime;
quelle