Qt'owe strumienie - brak operatora bool

1

Cześć!

Strumienie w Qt są bardzo fajne, lecz brakuje im tego jednego bardzo ułatwiającego życie operatora który występuje w strumieniach z std

while(stream >> value){

}

Tym operatorem jest bool który powoduje że pętelka się kręci, dopóki nie pojawi się błąd w odczycie.

Powiem Wam, że w Qt kombinuję, wymyślam, może by dziedziczyć, jakoś dopisać operator, po chwili zastanowienia zapisałem to tak:

#include <QDebug>
#include <QDataStream>

int main(){
    char a[] = {1, 2, 3, 2, 1};
    QDataStream stream(a);

    quint8 v;

    while((stream >> v).status() == QDataStream::Ok){
        qDebug() << v;
    }

    return 0;
}

Jest ok, lecz zapis jest droszkę długi i doprowadza mnie do tego:

#include <QDebug>
#include <QDataStream>

#define STREAM_WHILE(...) while((__VA_ARGS__).status() == QDataStream::Ok)

int main(){
    char a[] = {1, 2, 3, 2, 1};
    QDataStream stream(a);

    quint8 v;

    STREAM_WHILE(stream >> v){
        qDebug() << v;
    }

    return 0;
}

A powyższy define doprowadza do szaleństwa... zamiast lepiej jest gorzej.

Staram się troszkę zwiększyć czytelność i zmniejszyć ilość kodu w jednym ze starszych moich projektów.
Mam coś takiego:

for(;;){
    stream >> ev;
    if(stream.status() != QDataStream::Ok || ev.endOfTrack())
        break;
    mEvent.append(ev);
}

A wolałbym tak:

while( (stream >> ev) && !ev.endOfTrack() )
    mEvent.append(ev);

Proszę doradźcie coś, bo z brakiem operatora bool, to tak kombinuję że same kwiatki wychodzą :(

0

Może tak?

#include <QDebug>
#include <QDataStream>

template<class T = const QDataStream>
bool check(T&t){
    return t.status() == T::Ok;
}

int main(){
    char a[] = {1, 2, 3, 2, 1};
    QDataStream stream(a);

    quint8 v;

    while(check(stream >> v))
        qDebug() << v;


    return 0;
}
0

Nie można zdefiniować operatora bool, ale można zdefiniować operator negacji.

bool operator!(const QDataStream& stream)
{
    return stream.status() != QDataStream::Ok;
}

while (!!(stream >> ev) && !ev.endOfTrack())
    mEvent.append(ev);

if (!(stream >> ev) || ev.endOfTrack())
    break;
1

QDataStream to nie to samo co std::stream.
Pierwsze operuje na danych binarnych i ma zapewnić spójność zapisu binarnego na wszystkich platformach (pilnuje endiany, rozmiaru danych, formatu danych zmiennoprzecinkowych. Zwykle rozmiar danych binarnych do wczytania jest dobrze zdefiniowany.
Drugie operuje na danych tekstowych i dokonuje konwersji z zapisu tekstowego.

Takie kombinacje z makrami i operatorami utrudniają pracę później. Kod pisze się raz czyta 20 razy.
Radzę przejrzeć przykłady Qt i trzymać się tych samych standardów.

Może dla własnego dobra opisz jaki jest twój pierwotny problem, bo mam wrażenie, że używasz QDataStream na wyrost.
Przykładowo ten kod (minimalna zmiana) nie zrobi tego co oczekujesz:

int main(){
    qint32 a[] = {1, 2, 3, 2, 1, 0 }; // w twoim kodzie brakuje zera na końcu masz UB
    QByteArray data((char *)&a, sizeof(a));
    QDataStream stream(data);
 
    qint32 v;
 
    while((stream >> v).status() == QDataStream::Ok){
        qDebug() << v;
    }
 
    return 0;
}

Pierwszy wpis zapewne wydrukuje ci 16777216 a nie 1

0
MarekR22 napisał(a):

QDataStream to nie to samo co std::stream.
Pierwsze operuje na danych binarnych i ma zapewnić spójność zapisu binarnego na wszystkich platformach (pilnuje endiany, rozmiaru danych, formatu danych zmiennoprzecinkowych. Zwykle rozmiar danych binarnych do wczytania jest dobrze zdefiniowany.
Drugie operuje na danych tekstowych i dokonuje konwersji z zapisu tekstowego.

Tak, pisałem o tym, że operator bool w std::stream jest bardzo intuicyjny i brakuje go w QDataStream.

MarekR22 napisał(a):

Takie kombinacje z makrami i operatorami utrudniają pracę później. Kod pisze się raz czyta 20 razy.

Dlatego nie chcę przekombinować, ale też nie chcę zostawiać przy dość niewygodnej formie.
Wolę dorobić sobię chociaż tą funkcję check - może ją lepiej nazwać i będzie cacy.

MarekR22 napisał(a):

Może dla własnego dobra opisz jaki jest twój pierwotny problem, bo mam wrażenie, że używasz QDataStream na wyrost.

Przepisuję biblioteczkę do obsługi pewnych formatów plików.

MarekR22 napisał(a):

Przykładowo ten kod (minimalna zmiana) nie zrobi tego co oczekujesz:

Zawsze określam kolejność bajtów, więc nie widzę co jest tu nadzwyczajnego.

Co do UB, to faktycznie, popełniłem błąd, po prostu na szybko zrobiłem jakiś przykład z czytaniem danych (dla forum), bo u mnie jedzie po pliku.

Nie chcę rozpoczytać dyskusji na temat czy jest to potrzebne, czy nie potrzebne, czy używać QDataStream, czy coś innego.
W tym temacie poruszam problem braku operatora bool.

Założę się że wielu z Was, znając C++ i poznawając Qt, a dokładnie strumienie, była mile zaskoczona (przynajmniej ja byłem) ;)
Ogromną zaletą było to, że co się wpisze do strumienia (zapisywany jest dodatowo rozmiar), tak się odczyta (w std wpisane 2 stringi bez spacji odczytywane sa jako 1).
Znów wadą było brak możliwości zapisu:

while(stream >> variable){
// do stuff
}

Myślę że duża część z Was, upewniała się czy na pewno w Qt nie da się tak zrobić.
Ciekawi mnie, czemu twórcy nie dopisali operatora bool dla swoich strumieni ?!
Wiem że takiego zapisu nie uzyskam nie modyfikując klas strumieni, dlatego szukam jakiś kompromis, bo zapis:

while((stream >> variable).status() == QDataStream::Ok){
// do stuff
}

Mnie dość denerwuje.

1 użytkowników online, w tym zalogowanych: 0, gości: 1