[Road for Qt 6] Modifiche a QMetaType e QVariant

Uno dei più grossi miglioramenti strutturali su Qt 6 è certamente dovuto al potere utilizzare C++17 come base per il codice. In questo modo si può sfruttare tutta la potenza del C++ Modern 1z rendendo disponibili nuove funzionalità o permettendo di potenziare quelle già esistenti.

Dopo il precedente articolo sull’unificazione dei container, questa volta parlerò delle modifiche annunciate riguardo due elementi fondamentali del framework Qt, ovvero QMetaType e QVariant. Come effetto delle migliorie, vedremo come in Qt 6 sarà possibile dichiarare e registrare i propri tipi in modo molto più semplice di adesso.


QMetaType

QMetaType è la classe delegata a fornire meta-info sui tipi delle classi all’interno del meta-object system di Qt. Avere queste informazioni aggiuntive permette la creazione e distruzione di tipi a partire da un nome. QMetaType è utilizzato principalmante da QVariant e nei signal-slot per ottenere le informazioni necessarie sul tipo che stanno utilizzando.

Il potenziamento di QMetaType include l’essere ora un tipo copiabile e che adesso i tipi sono costruibili anche a compile-time. Se prima era necessario istanziare un QMetaType tramite

QMetaType oldWay1 = QMetaType::fromName("KnownTypeName");

oppure

QMetaType oldWay2(knownTypeID);

adesso è possibile ed incentivato a usare la sua forma a compile-time

QMetaType newWay = QMetaType::fromType<MyType>();

Le prime due possibilità rimangono disponibili qualora non si conoscesse il tipo a tempo di compilazione.


QVariant

QVariant rappresenta il fulcro di tutti i tipi Qt, essendo una union che può contenere tutti i tipi base di C++ più praticamente ogni classe dati di Qt. È utilizzato quando è necessario specificare un tipo generico all’interno delle API, ne possiamo un utilizzo massivo all’interno dei QAbstractItemModel per potere implementare un’interfaccia per il Model-View-Delegate. QVariant può essere anche estesa aggiungendo delle nostre classi ai tipi supportati al suo interno.

Il potenziamento di QMetaType permette un potenziamento anche su QVariant:

  • La comparazione QVariant avverrà tramite QMetaType::equals().
  • QVariant includerà il metodo QVariant::compare() che ritorna un std::optional con std::nullopt in caso la comparazione non sia possibile.
  • Il metodo isNull() adesso è stato uniformato per tutti i tipi e ritornerà vero solo nel caso un QVariant sia vuoto o al suo interno contenga un nullptr.
  • Sarà possibile costruire un QVariant direttamente da un QMetaType.

Adesso passiamo alla parte sicuramente più interessante delle nuove modifiche

Registrazioni dei tipi più semplice

Sappiamo che per registrare una classe custom nel meta-object system è necessario soddisfare regole sulla presenza di un costruttore di default e di un costruttore di copia (per permettere come detto prima di essere istanziati tramite QMetaType). Inoltre, era necessario:

  • Dichiarare il nuovo tipo tramite Q_DECLARE_METATYPE.
  • Registrare il nuovo tipo tramite qRegisterMetaType.

In aggiunta, in presenza di operatore di debug, operatore di stream, comparatori e converter scritti per il nuovo tipo era necessario registare anche loro esplicitamente.

In Qt 6 si potrà fare a meno della maggior parte di questi, grazie al potenziamento delle capacità di reflection non sarà più necessario utilizzare le seguenti dichiarazioni:

  • Q_DECLARE_METATYPE
  • QMetaType::RegisterEqualsComparator()
  • QMetaType::RegisterComparators()
  • QMetaType::RegisterDebugStreamOperator()
  • qRegisterMetaTypeStreamOperator()

Rimarrà tuttavia ancora necessario registrare i converter tramite QMetaType::RegisterConverterFunction() e utilizzare qRegisterMetaType() per permettere al nuovo tipo di essere utilizzato come parametro di un segnale in un signal-slot, ma rimane un grosso passo avanti soprattutto perché Q_DECLARE_METATYPE e QMetaType::RegisterDebugStreamOperator() sono quelli più utilizzati in assoluto.

Per chi volesse leggere l’articolo completo riguardo tutte le modifiche, può andare sul blog post del QtBlog.

Lascia un commento