QVariant ist da garantiert keine Lösung. Eine "Datenstruktur" macht nur Sinn, wenn alle Daten darin irgendwie verwandt sind oder etwas miteinander zu run haben.
Schau dir XML an: Du hast lauter Nodes. Eine Node kann jetzt aber verschiedene Ausprägungen haben: Element, Attribute, CDATA, usw. Es gibt daher in den DOM-Implementierungen eine gemeinsame Basisklasse: Node. Die spezialisierten Nodes (Element, ...) erben von Node. Beim Parsen werden die speziellen Klassen instantiiert und als Node in den Dom-Tree eingefügt. Node hat wiederum ein attribut "type", über das die spezielle Klasse identifiziert werden kann. Beim Iterieren über alle nodes eines trees kannst du nun node.tree() anschauen und entsprechend in den korrekten Typ casten.
So viel zur Parallele. Dein Problem lässt sich ähnlich lösen. Erstell dir eine KLasse "BaseObject" (Benennung sollte natürlich passender sein

), die alle Eigenschaften implementiert, welche allen Typen gemein ist. Nun kannst du für deine ganzen speziellen Fälle eigene Klassen ableiten. Diese kannst du nun als "BaseObject" in deiner Datenstruktur ablegen. So hast du gleich mehrere Fliegen mit einer Klappe geschlagen:
* Die Daten liegen in der abgeleiteten Klasse so vor wie sie sollen: als konkreter Typ (QPair, ...), nicht als QVariant.
* Du kannst deine Daten direkt identifizieren (Klasse eben), und musst nicht erst halsbrecherisch mit Variants schonglieren (was nebenbei auch ziemlich auf die Performance geht)
* Eine "liste" ist jetzt nicht mehr eine QVariantList, sondern eine parent-node mit children! Das ist SOFORT(!) identifizierbar.
* Typunterscheidung und casten wird zum großen Teil vom Compiler überwacht. Ein falscher Cast zur Lafzeit wie von QVariant auf irgend einen falschen Typ resultiert nicht (so leicht) in einem Laufzeitfehler.
Ich hoffe das war jetzt halbwegs klar. Da du leider noch nicht gesagt hast, was genau modelliert werden soll, kann ich noch keine konkreten (Pseudo)Klassen angeben.