Active Topics

 


Reply
Thread Tools
Posts: 124 | Thanked: 10 times | Joined on Jan 2007 @ Italy
#1
hi there!
i'm working with qt nokia sdk and i'm blocked with a strange issue with list serialization!
I've a QList of objects called Service(pointer of Service, QList<Service*>), and i've to store it in a QSetting file using a QDataStream. I've already overloaded << and >> operator for Service objects and they work well.
Now i'm trying to save all the list, but:

error: no match for ‘operator>>’ in ‘data >> ((MainList*)this)->MainList::services’
the strange thing is that << seems to work with QList<Service*>!

here some snap of my code:

Code:
#ifndef SERVICE_H
#define SERVICE_H
#include <QString>
#include "qmetatype.h"

class Service
{
public:
    Service();
    Service(QString name, QString address, bool needU, QString user,
            bool needP, QString password, bool needN, QString nick, bool active);
    QString getName();
    QString getAddress();
    QString getUser();
    QString getPassword();
    QString getNick();
    ..........
    bool isActive();
    bool needUser();
    bool needPass();
    bool needNick();

private:
    QString name;
    QString address;
    QString user;
    QString password;
    QString nick;
    bool active;
    bool needU;
    bool needP;
    bool needN;
};
QDataStream &operator<<(QDataStream &out,  Service &service);
QDataStream &operator>>(QDataStream &in, Service &service);
Q_DECLARE_METATYPE(Service*);

#endif // SERVICE_H
Code:
#include "service.h"
#include <QStringList>
#include <QDebug>


Service::Service()
{
    this->name="";
    this->address="";
    this->user="";
    this->password="";
    this->nick="";
    this->active=true;
}

Service::Service(QString name, QString address, bool needU, QString user,
        bool needP, QString password, bool needN, QString nick,bool active){
    this->name=name;
    this->address=address;
    this->user=user;
    this->password=password;
    this->nick=nick;
    this->needN=needN;
    this->needP=needP;
    this->needU=needU;
    this->active=active;

}

QString Service::getAddress(){
    return address;
}
QString Service::getName(){
    return name;
}

QString Service::getUser(){
    return user;
}
QString Service::getPassword(){
    return password;
}

QString Service::getNick(){
    return nick;
}

.......

bool Service::isActive(){
    return this->active;
}

bool Service::needUser(){
    return this->needU;
}
bool Service::needPass(){
    return this->needP;
}
bool Service::needNick(){
    return this->needN;
}

QDataStream &operator<<(QDataStream &out,  Service &service)
{
    out << service.getName() << service.getAddress() << service.needUser() << service.getUser()
            << service.needPass() << service.getPassword() << service.needNick() << service.getNick()
            << service.isActive();

    return out;
}

QDataStream &operator>>(QDataStream &in, Service &service)
{
    QString name;
    QString address;
    QString user;
    QString password;
    QString nick;
    bool needU, needP, needN, active;

    in >> name >> address >> needU >> user >> needP >> password >> needN >> nick >> active;
    service = Service(name, address, needU, user, needP, password, needN, nick, active);
    return in;
}
and here how i'm using it:
load:
Code:
QVariant var = settings->value("services");
        QByteArray array;
        array =var.value<QByteArray>();
        QDataStream data(&array,QIODevice::ReadWrite);
       data >> services;
save:
Code:
 QByteArray array;
       QDataStream data(&array, QIODevice::ReadWrite);
       data << services;
       QVariant var;
       var.setValue(array);
       //}
    settings->setValue("services", var);
where:
QList<Service*> *services;

i hope u can help me
 
Posts: 190 | Thanked: 129 times | Joined on Mar 2010 @ Bavaria, Germany
#2
First, please make the writing function const.
Code:
QDataStream &operator<<(QDataStream &out,  const Service &service);
QDataStream &operator>>(QDataStream &in, Service &service);
The second is, you can only use non-pointer types of Service when exporting the whole QList to a QDataStream. The following would work:
Code:
QList<Service> services;
mystream << services;
If you can't change to non-pointer type, you will have to iterate through the list at your own.
Code:
QList<Service*> services;
mystream << services.size();
foreach(Service* service, services)
  mystream << *service;
Edit: Also please stay away from creating QList<>s on the heap

the strange thing is that << seems to work with QList<Service*>!
If that's the only problem, try this:
Code:
mystream << *services;

Last edited by gri; 2010-06-03 at 21:52.
 

The Following 2 Users Say Thank You to gri For This Useful Post:
Posts: 124 | Thanked: 10 times | Joined on Jan 2007 @ Italy
#3
Originally Posted by gri View Post
First, please make the writing function const.
Code:
QDataStream &operator<<(QDataStream &out,  const Service &service);
QDataStream &operator>>(QDataStream &in, Service &service);
mmm why do that?! btw if i make it const i've this:
Code:
 error: passing ‘const Service’ as ‘this’ argument of ‘QString Service::getName()’ discards qualifiers
To solve i've to add const in getName()(and other get metods), like:
getName() const { return name;}



Originally Posted by gri View Post
The second is, you can only use non-pointer types of Service when exporting the whole QList to a QDataStream. The following would work:
Code:
QList<Service> services;
mystream << services;
that's would be good, but i've to pass these pointers to other class in order to edit them, so i think i can't use non-pointer...am i right?!



Originally Posted by gri View Post
If you can't change to non-pointer type, you will have to iterate through the list at your own.
Code:
QList<Service*> services;
mystream << services.size();
foreach(Service* service, services)
  mystream << *service;
nice this way, but...should i store manually the list's size before store elements?



Originally Posted by gri View Post
Edit: Also please stay away from creating QList<>s on the heap
what's the matter with this?! i'm still so confused about reference and pointer

Last edited by saxen; 2010-06-03 at 22:02.
 
Posts: 726 | Thanked: 345 times | Joined on Apr 2010 @ Sweden
#4
what's the matter with this?! i'm still so confused about reference and pointer
Pointers refer to any memory, be it on the stack or the heap. Where you allocate it has nothing to do with the pointer per se.

But, when the memory is deallocated (using delete or leaving the current scope) the pointer points at memory that you can not access without triggering an error.

References share some of the pointer semantics but have some extra constraints and properties. For one, a reference always has to have a value that can be referenced. (Hence the name.)
 

The Following 2 Users Say Thank You to Joorin For This Useful Post:
Venemo's Avatar
Posts: 1,296 | Thanked: 1,773 times | Joined on Aug 2009 @ Budapest, Hungary
#5
Hey,

I also encountered the exact same situation.
Gri and the others wrote down everything well, but let me add a few side notes.

You can basically serialize a QList<T> if T is serializable. (Meaning: it has a << operator.)

I wrote for myself a class called QSettingsManager for this purpose. You can view the code here and the entire app in this repository.

Feel free to use it in your app, too.
There are also examples for serialization, too.

The relevant part is this:

Code:
template<typename T>
void QSettingsManager::storeBinary(const QString& key, const T& value)
{
    checkSettingsObj();
    QByteArray array;
    QDataStream stream(&array, QIODevice::WriteOnly);
    stream << value;
    storeSetting(key, array);
}
You can call it like this, for example:

Code:
QList<QString> myList;
... // fill myList with values
QSettingsManager::storeBinary<QList<QString> >("settingskey", myList);
 

The Following User Says Thank You to Venemo For This Useful Post:
Posts: 190 | Thanked: 129 times | Joined on Mar 2010 @ Bavaria, Germany
#6
Code:
 error: passing ‘const Service’ as ‘this’ argument of ‘QString Service::getName()’ discards qualifiers
Getters should always be const! So the error message is right.

that's would be good, but i've to pass these pointers to other class in order to edit them, so i think i can't use non-pointer...am i right?!
You should read something about pointer dereferencing. Also non-pointer variables can be made to pointer variables and vice versa.
Code:
Service service;
Service* servicePointer = &service;
Service& serviceReference = service;
Service& serviceReferenceFromPointer = *service;
nice this way, but...should i store manually the list's size before store elements?
Otherwise you won't know how much elements you have to read the next time If you create a QList<Service*> and call the shift operator for the QDataStream, your datastream will fill something strange (or it crashes). Since the QList operator for the QDataStream does not know that it should create a Service instance with "new".

what's the matter with this?! i'm still so confused about reference and pointer
References and pointers are the same in some ways. I can't explain this in english, maybe you should read some c++ tutorials for that.
 

The Following User Says Thank You to gri For This Useful Post:
Posts: 124 | Thanked: 10 times | Joined on Jan 2007 @ Italy
#7
thanks for explanation joorin

Originally Posted by Venemo View Post

You can basically serialize a QList<T> if T is serializable. (Meaning: it has a << operator.)
that's why i said that << and >> work well with "Service*". so T is serializable!

Originally Posted by Venemo View Post
I wrote for myself a class called QSettingsManager for this purpose. You can view the code here and the entire app in this repository.
is this?!
http://vcs.maemo.org/svn/eve-watcher...ngsmanager.cpp


now i'm going to try this:
1) put away QList<> from the heap
2) try to use QList<Service> instead of QList<Service*>
3) if 2 won't work, i'll try to save element by element.


@gri, if i can use non-pointer to do that...i wonder...when a pointer is necessary!?
 
Venemo's Avatar
Posts: 1,296 | Thanked: 1,773 times | Joined on Aug 2009 @ Budapest, Hungary
#8
Originally Posted by saxen View Post
is this?!
http://vcs.maemo.org/svn/eve-watcher...ngsmanager.cpp
Yeah, plus the header file.
(The template methods which I quoted earlier are in the header file.)
You can check out the entire app so you can see how it works, if you wish.

Originally Posted by saxen View Post
that's why i said that << and >> work well with "Service*". so T is serializable!
A pointer is an address in the memory.
It is (basically) a 32-bit integer of 32-bit machines and a 64-bit integer on 64-bit machines.
Because of this, every pointer is "serializable". Still, you don't gain anything by storing a random memory address.

Why?
1. There is no guarantee that the same address will be yours next time.
2. The data stored in that address is erased when your app is closed, so no point in storing its address anyway.

Solution:
Store the data itself, not its address.

Originally Posted by saxen View Post
@gri, if i can use non-pointer to do that...i wonder...when a pointer is necessary!?
Pointers are necessary for a range of nasty things.
This simple task is not one of them.

Last edited by Venemo; 2010-06-03 at 22:34.
 

The Following User Says Thank You to Venemo For This Useful Post:
Posts: 726 | Thanked: 345 times | Joined on Apr 2010 @ Sweden
#9
This isn't directly related to you question, but it might explain something.

Code:
int i = 17;
int *pointer_to_int = &i;
The above snippet describes storage of an integer, 17, and a pointer to the address in memory where this integer is stored.

Using this pointer, you can change the stored value:
Code:
*pointer_to_int = 4711;
The pointer lets you pass around data in the form of a reference that, when dereferenced, gives you the actual data.

Continuing from above, you can extend this indirection:
Code:
int **pointer_to_pointer_to_int = &pointer_to_int;
This describes a pointer pointing to a pointer pointing at an integer, 17, which lets you manipulate both the integer and the pointer that points to it. Further indirection is possible but this is often the level that is interesting because being able to change what a pointer points to instead of the value that the pointer point to let's you, for example, iterate over lists or return pointers from functions.

Code:
int do_stuff(char *foo, char **error) {
  ...
}
By calling do_stuff with a pointer to a pointer, it is possible to return a pointer to something that has been allocated inside do_stuff.

References can in most cases be seen as lacking the second level of indirection. The compiler imposes limitations on what you can do with a reference and dictates when they have to be initialized. It is not interesting to change references like pointers because the reference already gives you direct access to whatever it references

If you play around with it a bit, you'll understand more. Take the time to look at one of the many introductions to C++ online.

Last edited by Joorin; 2010-06-03 at 22:49.
 
Posts: 124 | Thanked: 10 times | Joined on Jan 2007 @ Italy
#10
ok with 2) i've solve problem with >> operator...but anything else is working xD

i'm sure is a reference/pointer stuff. i mean, i'm adding to my QList<Service> a reference Service service in a method called "addItems". Will it be this reference deleted once the addItems is over even if it's now linked in my list?!

so should i use Service * service = new Service() and then add with list->append(*service) ?!
 
Reply


 
Forum Jump


All times are GMT. The time now is 21:03.