Seite 1 von 1

[gelöst] conversation vector<string> zu QStringList

Verfasst: 13. November 2006 21:39
von QtBerserker
Hi,

gibt es einen (einfachen) Weg zur Konversation von vector<string> zu QStringList und umgekehrt? Meine bisherigen Versuche endeten einfach zu kompliziert.

Grüße
Olaf

Verfasst: 13. November 2006 22:12
von Christian81
Mir ist da auch keine Funktion bekannt - musst wohl oder übel über alle Items iterieren und mit QString::fromStdString() konvertieren...

Verfasst: 14. November 2006 19:15
von QtBerserker
Christian81 hat geschrieben:Mir ist da auch keine Funktion bekannt - musst wohl oder übel über alle Items iterieren und mit QString::fromStdString() konvertieren...
Ok, in Analogie zur STL:

Code: Alles auswählen

namespace Qt {
    typedef std::vector<std::string>::iterator input_iterator;
    typedef QList<QString>::iterator output_iterator;

    output_iterator copy(input_iterator from_first, input_iterator from_last,  output_iterator to_first)
    {
        while (from_first != from_last) {
            to_first->fromStdString(*from_first);
            ++from_first;
            ++to_first;
        }
        return to_first;
    }
}
Olaf

Verfasst: 15. November 2006 11:28
von lepsai
return braucht man nicht, also:

Code: Alles auswählen

namespace Qt { 
    typedef std::vector<std::string>::iterator input_iterator; 
    typedef QList<QString>::iterator output_iterator; 

    void copy(input_iterator from_first, input_iterator from_last,  output_iterator to_first, output_iterator to_last) 
    { 
        while (from_first != from_last  && to_first != to_last) { 
            to_first->fromStdString(*from_first); 
            ++from_first; 
            ++to_first; 
        } 
    } 
} 

std::vector<std::string> v1;
QStringList v2;

copy(v1.begin(), v1.end(), v2.begin(), v2.end());


Verfasst: 15. November 2006 11:36
von Christian81
Ich verstehe nicht was v2.begin(), v2.end() soll - da muss doch somit davor erst die QStringList gross genug gemacht werden...
Was ist gegen

Code: Alles auswählen

v2 += QString::fromStdStringQString::fromStdString(*from_first);
einzuwenden?

Verfasst: 15. November 2006 17:33
von lepsai
Christian81 hat geschrieben:Ich verstehe nicht was v2.begin(), v2.end() soll - da muss doch somit davor erst die QStringList gross genug gemacht werden...
Was ist gegen

Code: Alles auswählen

v2 += QString::fromStdStringQString::fromStdString(*from_first);
einzuwenden?
Die Vektoren mussen sowieso gleich groß sein, sonst funktioniert die while-schleife in dieser Implementierung nicht. ..

Verfasst: 15. November 2006 17:44
von Christian81
lepsai hat geschrieben: Die Vektoren mussen sowieso gleich groß sein, sonst funktioniert die while-schleife in dieser Implementierung nicht. ..
Das meine ich ja - total überflüssig die QStringList in der Grösse festlegen zu müssen...

Verfasst: 15. November 2006 18:14
von lepsai
nun ja, die engültige konvertierung würde in dem hier beschriebenen Fall dann so aussehen:

Code: Alles auswählen

template <typename InIt>
QStrlingList convertFromStdStringContainer(InIt begIt, InIt endIt){
   QStringList output;
   output.resize(endIt-begIt);
    
   copy(begIt, endIt, output.begin(), output.end()); 
   return output;
}
die copy() funktion müsste man dann auch anpassen, so dass sie nicht nur mit std::vector::iterator arbeiten kann, sondern den iteratortyp als template argument bekommt...

dann hätte man eine universelle Konvertierung von einem std::string-Kontainer zu QStringList.

Was Du vorschlägst funktioniert natürlich auch...

Verfasst: 15. November 2006 20:26
von QtBerserker
gut, die erste Lösung war etwas holprig, wie Euch bereits aufgefallen ist, muss der QListVector erst'mal resized werden.

Hier eine neue Lösung, die auch den assert Test (stdsv.size() == qtsl.size()) bestand:

Code: Alles auswählen

namespace std {

    template<>
    class back_insert_iterator<QStringList> : public iterator<output_iterator_tag, void, void, void, void>
    {
    protected:
        QStringList* container;

    public:
        typedef QStringList          		qcontainer_type;
        typedef std::vector<std::string> 	scontainer_type;

        explicit back_insert_iterator(qcontainer_type& x)
            : container(&x)
        { }

        back_insert_iterator& operator=(scontainer_type::const_reference value) {
            container->push_back(QString().fromStdString(value));
            return *this;
        }

        back_insert_iterator& operator*() { return *this; }
        back_insert_iterator& operator++() { return *this; }
        back_insert_iterator  operator++(int) { return *this; }
    };

    template<>
    inline back_insert_iterator<QStringList>
    back_inserter(QStringList& x) { return back_insert_iterator<QStringList>(x); }

}
using:

Code: Alles auswählen

std::copy(first, last,std::back_inserter(qtstrlst));
Diese Lösung funzt zumindest für den g++ 4.1.2, wobei die zweite Spezialisierung mit dem g++ nicht notwendig ist, evtl. aber bei VC notwendig wird. Prinzipiell kann man somit auch andere Qt Sachen spezialisieren. So, nun macht mich fertig ;-)

Olaf

Verfasst: 15. November 2006 21:50
von lepsai
Nun ja, das wäre eine STL-konforme Lösung... Die lässt sich aber für alle Kontainertypen verallgemeinern:

Code: Alles auswählen

namespace std {

    template<typename InputContainerType>
    class back_insert_iterator: public iterator<output_iterator_tag, void, void, void, void>
    {
    protected:
        QStringList* container;

    public:
        typedef QStringList          		qcontainer_type;
        typedef InputContainerType	scontainer_type;

        explicit back_insert_iterator(qcontainer_type& x)
            : container(&x)
        { }

        back_insert_iterator& operator=(scontainer_type::const_reference value) {
            container->push_back(QString().fromStdString(value));
            return *this;
        }

        back_insert_iterator& operator*() { return *this; }
        back_insert_iterator& operator++() { return *this; }
        back_insert_iterator  operator++(int) { return *this; }
    };

    template<typename InputContainerType>
    inline back_insert_iterator
    back_inserter(QStringList& x) { return back_insert_iterator<InputContainerType>(x); }

}
using:

Code: Alles auswählen

std::copy(first, last,std::back_inserter(qtstrlst));

Verfasst: 16. November 2006 18:50
von QtBerserker
so einfach geht das leider nicht, zum einen klemmt's bei std::back_inserter(qtstrlst), da der Template Parameter dann QStringList wäre, zum anderen gibt es eine Neudefinition von template back_insert_iterator. Imo kommt man um eine Spezialiserung des back_insert_iterators nicht umhin - wenn man diesen Weg wählen möchte.

Olaf

Verfasst: 16. November 2006 19:24
von lepsai
QtBerserker hat geschrieben:so einfach geht das leider nicht, zum einen klemmt's bei std::back_inserter(qtstrlst), da der Template Parameter dann QStringList wäre, zum anderen gibt es eine Neudefinition von template back_insert_iterator. Imo kommt man um eine Spezialiserung des back_insert_iterators nicht umhin - wenn man diesen Weg wählen möchte.

Olaf
QStringList braucht man nicht als template argument, da es fest ist... Also, wo liegt das Problem?