How to append struct to QList?



  • Hi
    Is there a more elegant way to append a custom struct data type to a QList?
    Lets say I have this custom struct and declared QList of that same type:

    struct Blood{
    	QDateTime dateTime;
    	unsigned int systole;
    	unsigned int diastole;
    	unsigned int puls;
    };
    ...
    private:
    	QList<Blood> readDataList;
    
    

    Now I want to append new values to the list (by going through a SQL source), I did this:

    Blood tempValue;
    while (query.next()) {
    			tempValue.dateTime = QDateTime::fromString(query.value(0).toString(), "dd.MM.yyyy-hh:mm");
    			tempValue.systole = query.value(1).toInt();
    			tempValue.diastole = query.value(2).toInt();
    			tempValue.puls = query.value(3).toInt();
    			readDataList.append(tempValue);
    		}
    

    this works, but is there a shorter way doing this? Something like this in one line without tempValue?:

    readDataList.append(Blood(QDateTime::fromString(query.value(0).toString(), "dd.MM.yyyy-hh:mm") ,query.value(1).toInt(),query.value(2).toInt(),query.value(3).toInt());
    

  • Moderators

    @pauledd said in How to append struct to QList?:
    Basically you can see a struct as a class (just with different default visibility).
    So you are able to add methods and also a constructor to the struct.

    struct Blood{
            Blood(QDateTime dt, unsigned int s, unsigned int d, unsigned int p)
                 : dateTime(dt), systole(s), diastole(d), puls(p)
            {
            }
    
    	QDateTime dateTime;
    	unsigned int systole;
    	unsigned int diastole;
    	unsigned int puls;
    };
    ....
    readDataList << Blood(QDateTime::fromString(query.value(0).toString(), "dd.MM.yyyy-hh:mm") ,query.value(1).toInt(),query.value(2).toInt(),query.value(3).toInt();
    


  • Your class should be assignable to go in a QList:

    To qualify, a type must provide a default constructor, a copy constructor, and an assignment operator.

    I think in your case they are created by the compiler but it probably is a good idea to make them explicit together with a
    Blood(const QDateTime& dt, unsigned int s, unsigned int d, unsigned int p) constructor as suggested above



  • Thank you both! It works.
    @VRonin and why you only use const & with the QDateTime and not with the int's too?



  • @pauledd said in How to append struct to QList?:

    @VRonin and why you only use const & with the QDateTime and not with the int's too?

    My general rule is: if the data is greater than 64 bits, pass it by const reference.

    QDateTime might be borderline as inside it probably just contains a quint64 but I pass it by const reference to be safe, the ints are (normally) 32 bits so they can go by value with no expense


  • Moderators

    @pauledd said in How to append struct to QList?:

    why you only use const & with the QDateTime and not with the int's too?

    because you wont gain any/much benefit (efficiency) from it. With the const reference you save one copy instruction.



  • Thanks a lot! Marked as solved.



  • Just one more question arose

    @VRonin said in How to append struct to QList?:

    To qualify, a type must provide a ... and an assignment operator.

    Does the assignment operator look correct? (it compiles fine):

    struct Blood{
    	Blood(const QDateTime& dt, unsigned int s, unsigned int d, unsigned int p)
    		:dateTime(dt),systole(s),diastole(d),puls(p){}
    	Blood(){}
    	
    	QDateTime dateTime;
    	unsigned int systole;
    	unsigned int diastole;
    	unsigned int puls;
    	
    	friend QDataStream &operator<<(QDataStream &out, const Blood& blood){
    		out << blood.dateTime << blood.systole << blood.diastole << blood.puls;
    		return out;
    	}
    };
    


  • That's not an assignment operator. see http://www.cplusplus.com/doc/tutorial/classes2/#copy_assignment

    class Blood{
    public:
    	Blood(const QDateTime& dt, unsigned int s, unsigned int d, unsigned int p)
    		:dateTime(dt),systole(s),diastole(d),puls(p){}
    	Blood() {} //Default constructor
    Blood(const Blood& other)
    :dateTime(other.dateTime ),systole(other.systole),diastole(other.diastole),puls(other.puls){} // Copy constructor
    	Blood& operator=(const Blood& other){
    dateTime = other.dateTime ;
    systole=other.systole;
    diastole=other.diastole;
    puls=other.puls;
    return *this;
    } //assingment operator
    
    // encapsulate members
    const QDateTime& dateTime() const { return dateTime;}
    void setDateTime(const QDateTime& val){dateTime=val;}
    unsigned int systole() const { return systole;}
    void setSystole(unsigned int val){systole=val;}
    unsigned int diastole() const { return diastole;}
    void setDiastole(unsigned int val){diastole=val;}
    unsigned int puls() const { return puls;}
    void setPuls(unsigned int val){puls=val;}
    
    private:
    	QDateTime dateTime;
    	unsigned int systole;
    	unsigned int diastole;
    	unsigned int puls;
    	
    };
    


  • Ok thanks, thats looks like I'll spend ages puzzling over this exercise.



  • More questions :(

    My little nice struct exploded to a huge class ;) that makes me considering to use my very first approach again.

    I just short read about assignment operator and in your assignment operator declaration shouldn't there also be a self-assigned test like this?

    ...
    if (this == &other) return *this;
    ...
    

    If I try your class I get a load of errors about previous declarations:
    alt text

    
    In file included from ../test1/blood.cpp:1:0:
    ../test1/blood.h:31:12: error: 'QDateTime Blood::dateTime' conflicts with a previous declaration
      QDateTime dateTime;
                ^
    ../test1/blood.h:21:18: note: previous declaration 'const QDateTime& Blood::dateTime() const'
     const QDateTime& dateTime() const { return dateTime;}
                      ^
    ../test1/blood.h:32:15: error: 'unsigned int Blood::systole' conflicts with a previous declaration
      unsigned int systole;
                   ^
    ../test1/blood.h:23:14: note: previous declaration 'unsigned int Blood::systole() const'
     unsigned int systole() const { return systole;}
                  ^
    ../test1/blood.h:33:15: error: 'unsigned int Blood::diastole' conflicts with a previous declaration
      unsigned int diastole;
                   ^
    ../test1/blood.h:25:14: note: previous declaration 'unsigned int Blood::diastole() const'
     unsigned int diastole() const { return diastole;}
                  ^
    ../test1/blood.h:34:15: error: 'unsigned int Blood::puls' conflicts with a previous declaration
      unsigned int puls;
                   ^
    ../test1/blood.h:27:14: note: previous declaration 'unsigned int Blood::puls() const'
     unsigned int puls() const { return puls;}
                  ^
    ../test1/blood.h: In constructor 'Blood::Blood(const QDateTime&, unsigned int, unsigned int, unsigned int)':
    ../test1/blood.h:8:4: error: class 'Blood' does not have any field named 'dateTime'
       :dateTime(dt),systole(s),diastole(d),puls(p){}
        ^
    ../test1/blood.h:8:17: error: class 'Blood' does not have any field named 'systole'
       :dateTime(dt),systole(s),diastole(d),puls(p){}
                     ^
    ../test1/blood.h:8:28: error: class 'Blood' does not have any field named 'diastole'
       :dateTime(dt),systole(s),diastole(d),puls(p){}
                                ^
    ../test1/blood.h:8:40: error: class 'Blood' does not have any field named 'puls'
       :dateTime(dt),systole(s),diastole(d),puls(p){}
                                            ^
    ../test1/blood.h: In copy constructor 'Blood::Blood(const Blood&)':
    ../test1/blood.h:11:2: error: class 'Blood' does not have any field named 'dateTime'
     :dateTime(other.dateTime ),systole(other.systole),diastole(other.diastole),puls(other.puls){} // Copy constructor
      ^
    ../test1/blood.h:11:28: error: class 'Blood' does not have any field named 'systole'
     :dateTime(other.dateTime ),systole(other.systole),diastole(other.diastole),puls(other.puls){} // Copy constructor
                                ^
    ../test1/blood.h:11:51: error: class 'Blood' does not have any field named 'diastole'
     :dateTime(other.dateTime ),systole(other.systole),diastole(other.diastole),puls(other.puls){} // Copy constructor
                                                       ^
    ../test1/blood.h:11:76: error: class 'Blood' does not have any field named 'puls'
     :dateTime(other.dateTime ),systole(other.systole),diastole(other.diastole),puls(other.puls){} // Copy constructor
                                                                                ^
    ../test1/blood.h: In member function 'Blood& Blood::operator=(const Blood&)':
    ../test1/blood.h:13:10: error: invalid use of member function (did you forget the '()' ?)
     dateTime = other.dateTime ;
              ^
    ../test1/blood.h:14:8: error: invalid use of member function (did you forget the '()' ?)
     systole=other.systole;
            ^
    ../test1/blood.h:15:9: error: invalid use of member function (did you forget the '()' ?)
     diastole=other.diastole;
             ^
    ../test1/blood.h:16:5: error: invalid use of member function (did you forget the '()' ?)
     puls=other.puls;
         ^
    ../test1/blood.h: In member function 'const QDateTime& Blood::dateTime() const':
    ../test1/blood.h:21:44: error: invalid initialization of reference of type 'const QDateTime&' from expression of type '<unresolved overloaded function type>'
     const QDateTime& dateTime() const { return dateTime;}
                                                ^
    ../test1/blood.h: In member function 'void Blood::setDateTime(const QDateTime&)':
    ../test1/blood.h:22:48: error: invalid use of member function (did you forget the '()' ?)
     void setDateTime(const QDateTime& val){dateTime=val;}
                                                    ^
    ../test1/blood.h: In member function 'unsigned int Blood::systole() const':
    ../test1/blood.h:23:39: error: cannot convert 'Blood::systole' from type 'unsigned int (Blood::)() const' to type 'unsigned int'
     unsigned int systole() const { return systole;}
                                           ^
    ../test1/blood.h: In member function 'void Blood::setSystole(unsigned int)':
    ../test1/blood.h:24:42: error: invalid use of member function (did you forget the '()' ?)
     void setSystole(unsigned int val){systole=val;}
                                              ^
    ../test1/blood.h: In member function 'unsigned int Blood::diastole() const':
    ../test1/blood.h:25:40: error: cannot convert 'Blood::diastole' from type 'unsigned int (Blood::)() const' to type 'unsigned int'
     unsigned int diastole() const { return diastole;}
                                            ^
    ../test1/blood.h: In member function 'void Blood::setDiastole(unsigned int)':
    ../test1/blood.h:26:44: error: invalid use of member function (did you forget the '()' ?)
     void setDiastole(unsigned int val){diastole=val;}
                                                ^
    ../test1/blood.h: In member function 'unsigned int Blood::puls() const':
    ../test1/blood.h:27:36: error: cannot convert 'Blood::puls' from type 'unsigned int (Blood::)() const' to type 'unsigned int'
     unsigned int puls() const { return puls;}
                                        ^
    ../test1/blood.h: In member function 'void Blood::setPuls(unsigned int)':
    ../test1/blood.h:28:36: error: invalid use of member function (did you forget the '()' ?)
     void setPuls(unsigned int val){puls=val;}
                                        ^
    ../test1/blood.cpp: At global scope:
    ../test1/blood.cpp:3:1: error: redefinition of 'Blood::Blood()'
     Blood::Blood()
     ^
    In file included from ../test1/blood.cpp:1:0:
    ../test1/blood.h:9:2: note: 'Blood::Blood()' previously defined here
      Blood() {} //Default constructor
      ^
    Makefile:885: recipe for target 'blood.o' failed
    

  • Qt Champions 2016

    @pauledd said in How to append struct to QList?:

    If I try your class I get a load of errors about previous declarations:

    You should resolve the errors, it's a trivial typo (conflicting function and member names):

    class Blood
    {
    public:
        // ...
        QDateTime dateTime() const;
        void setDateTime(const QDateTime &);
        //...
    
    private:
        DateTime _dateTime; //< Rename so it doesn't conflict with the method name
        // ...	
    };
    
    //< Good practice is to be explicit about inlined methods and makes for a lighter reading
    //< Also my advice is to return by value, not const references
    inline QDateTime Blood::dateTime() const 
    {
        return _dateTime;
    }
    
    inline void Blood::setDateTime(const QDateTime & val)
    {
        _dateTime = val;
    }
    


  • Thank you for the hints, I think I now have enough information to solve it.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.