J'ai un problème. Je travaille sur un projet où il y a pas mal de code qui utilise boost::any et pour bien comprendre comment ce code marche j'aimerais bien inspecter le type boost::any avec gdb pour afficher son contenu. Mon problème est que parfois je peux afficher le contenu de boost::any et parfois non.
(gdb) print boost::any_cast<int>(boost1)
No symbol "any_cast<int>" in namespace "boost".
On remarque assez rapidement que je ne peux pas inspecter boost::any si je n'ai pas un boost::any_cast présent dans mon code. Puisque boost::any_cast est un template, j'imagine que je ne peux pas utiliser ce template sans qu'il soit présent dans mon code car s'il n'est pas dans le code il n'est pas instancié...
Est-ce bien la vraie raison ou pas ?
Et surtout comment passer outre ce problème ?
Merci d'avance !
- Edité par ThomasAirain 1 décembre 2023 à 17:48:31
Salut, tu ne pourras effectivement pas utiliser une fonction template qui n'a jamais était instanciée. Mais il n'y a pas besoin de any_cast pour lire la valeur. En plus, cette fonction ne permet pas de connaître le type.
(gdb) p boost1
$5 = {content = 0x55555556d2b0}
Indique que boost::any contient un pointeur nommé content. Avec le débugueur, tout est accessible.
(gdb) p *boost1.content
$6 = {<boost::anys::detail::placeholder> = {
_vptr.placeholder = 0x555555559b68 <vtable for boost::any::holder<int>+16>}, <No data fields>}
content est de type boost::any::holder<int> et contient des fonctions virtuelles (le vptr et vtable).
(gdb) p (boost::any::holder<int>)*boost1.content
$7 = {<boost::any::placeholder> = {<boost::anys::detail::placeholder> = {
_vptr.placeholder = 0x555555559b68 <vtable for boost::any::holder<int>+16>}, <No data fields>},
held = 99}
</int>
Quand on cast le pointeur vers le bon holder, la valeur est visible dans held. On peut éliminer le bruit en l'affichant directement
(gdb) p ((boost::any::holder<int>)*boost1.content)->held
$8 = 99
Comme c'est assez fastidieux, le mieux et de faire un pretty-printers. J'ai trouvé celui-là pour boost, mais il n'y a pas any.
Salut ! Merci infiniment pour ta réponse ! Je bloquais depuis un moment là-dessus alors qu'en fait c'était assez simple !
En effet, il suffit d'aller voir le code de Boost pour voir qu'effectivement avec une commande de ce genre
((boost::any::holder<int>)*boost1.content)->held
On peut accéder à l'information qui nous intéresse ! Mais j'avoue que j'ai testé plein de techniques sauf ça.
Ce pretty-printer est pas mal, je l'utilise déjà car j'ai l'habitude de travailler sur des vieux projets avec Boost mais effectivement il n'y a rien pour boost::any
Je connais mal boost::any, mais je lis que ça permet de stocker n'importe quel type de variable. Ok.
J'imagine que bien des gens doivent faire des tableaux pour stocker des types hétérogènes.
Ma remarque viendrait plutôt du fait que - même avant de penser code - quand tu as besoin de stocker un tableau de types hétérogènes, il faut d'abord se poser la question de savoir s'il n'y a pas un soucis de conception en amont.
@Fvirtman: Il existe des cas où connaitre à l'avance le type de données à manipuler est particulièrement délicat, voir impossible (ou alors via une horrible gymnastique). Je pense à interagir dynamiquement avec une base de données par exemple.
Mais on est d'accord, bien qu'utile, l'utilisation de boost::any est et doit rester une utilisation de niche. Ce n'est d'ailleurs pas le seul, il y a plusieurs types "rare" présent dans la librairie standard.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html