2016-07-22 19 views
4

Wie extrahieren/drucken wir einzelne Werte in einem std :: tuple?GDB: Wie extrahieren wir Werte aus einem std :: tuple

Hier ist ein Beispielprogramm in einer Datei namens test.cc.

#include <tuple> 
#include <iostream> 

using namespace std; 

int main() { 
    auto t = make_tuple(111, 222); 
    cout << std::get<0>(t) << endl 
      << std::get<1>(t) << endl; 
    return 0; 
} 

kompilieren

g++ --std=c++11 -g test.cc 

Run es in GDB

gdb --args ./a.out 
... 
(gdb) start 
Temporary breakpoint 1 at 0x400836: file test.cc, line 7. 
Starting program: /home/fmlheureux/a.out 

Temporary breakpoint 1, main() at test.cc:7 
7   auto t = make_tuple(111, 222); 
(gdb) n 
9    << std::get<1>(t) << endl; 
(gdb) p t 
$1 = std::tuple containing = {[1] = 111, [2] = 222} 

Der letzte Befehl das Tupel als Ganzes gedruckt. Wie kann ich einzelne Werte extrahieren? Meine naiven Versuche scheitern.

(gdb) p get<0>(t) 
No symbol "get<0>" in current context. 
(gdb) p std::get<0>(t) 
No symbol "get<0>" in namespace "std". 
+0

Meine Lösung wäre, ein 'struct' anstelle eines' tuple' zu ​​verwenden. gdb kann damit umgehen. Natürlich sollte gdb nur Tuple-Zugriffe unterstützen ... – TheJJ

Antwort

4

Leider ist die hübsche-Druck-Code in gdb ein Nur-Anzeige-Funktion ist - also, während es auf eine nette Art ein Tupel hilft angezeigt werden, ist es nicht, dass Sie einen weiteren Zugriff es zulassen.

Das normale Problem mit etwas wie t.get<0> ist, dass diese winzigen Accessor-Methoden in der Regel vollständig vom Compiler optimiert werden - so dass es keine Kopie zum Aufruf gibt. Und während gdb ein "xmethod" -Feature hat, das verwendet werden kann, um gdb-seitige Python-Implementierungen dieser Accessoren zu liefern, zeigt info xmethods (zumindest für mich), dass noch niemand dies für std::tuple getan hat.

Sie haben also nur noch eine Option: die Implementierung überprüfen. Also, starten Sie durch das rohe Tupel Druck:

(gdb) p/r t 
$3 = {<std::_Tuple_impl<0ul, int, int>> = {<std::_Tuple_impl<1ul, int>> = {<std::_Head_base<1ul, int, false>> = { 
     _M_head_impl = 222}, <No data fields>}, <std::_Head_base<0ul, int, false>> = {_M_head_impl = 111}, <No data fields>}, <No data fields>} 

Hier können Sie die „echte“ Struktur des Tupels sehen, und die Felder direkt zugreifen:

(gdb) print ((std::_Head_base<1ul, int, false>) t)._M_head_impl 
$7 = 222 

Diese Umwandlung in einen Zwischentyp ist eine Art von einem Schmerz, wie? Es wird benötigt, damit gdb das korrekte Feld _M_head_impl auswählt. Wenn das etwas ist, das Sie planen, würde ich vorschlagen, das xmethod zu schreiben. Oder Sie könnten auch einfach eine Python-Komfortfunktion schreiben, um den Zugriff zu automatisieren; Diese Art von Introspektion ist mit der Python-API etwas einfacher zu machen.

+1

Danke für die Lösung! Für zukünftige Leser möchte ich darauf hinweisen, dass '1ul' der Index innerhalb des Tupels ist. –

Verwandte Themen