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:
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:
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?