Move the special QByteArrayList methods into QList

and make QByteArrayList be a simple typedef.

As a side-effect, the constructor taking a QByteArray is no longer
available since I couldn't find a way to add it to QList<T> when T is
QByteArray. My template-foo failed me. I tried:

 - QEnableIf<is_same<T, QByteArray>::value, QByteArray>::type
   => makes QList fail to compile for any T that isn't QByteArray
 - make the constructor a template member
   => it compiles if the parameter is a QByteArray, but not a const
      char[4] like the test was
 - inheriting constructors
   => runs into ICC and Clang bugs that I could not work around

Besides, the constructor with std::initializer_list is a superior
solution anyway.

Change-Id: Ic86fbadc1104142bfd907a5c4147199bf839fb89
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>
bb10
Thiago Macieira 2014-08-04 23:57:51 -03:00 committed by Oswald Buddenhagen
parent 2431bf1b20
commit dcf9883dff
5 changed files with 35 additions and 269 deletions

View File

@ -82,10 +82,9 @@ QT_BEGIN_NAMESPACE
\reentrant
QByteArrayList inherits from QList<QByteArray>. Like QList, QByteArrayList is
\l{implicitly shared}. It provides fast index-based access as well as fast
insertions and removals. Passing string lists as value parameters is both
fast and safe.
QByteArrayList is actually just a QList<QByteArray>. It is documented as a
full class just for simplicity of documenting the member methods that exist
only in QList<QByteArray>.
All of QList's functionality also applies to QByteArrayList. For example, you
can use isEmpty() to test whether the list is empty, and you can call
@ -105,88 +104,6 @@ QT_BEGIN_NAMESPACE
\sa QByteArray, QStringList
*/
/*!
\fn QByteArrayList::QByteArrayList()
Constructs an empty byte array list.
*/
/*!
\fn QByteArrayList::QByteArrayList(const QByteArray &ba)
Constructs a byte array list that contains the given byte array,
\a ba. Longer lists are easily created like this:
\snippet qbytearraylist/main.cpp 0
\sa append()
*/
/*!
\fn QByteArrayList::QByteArrayList(const QList<QByteArray> &other)
Constructs a copy of \a other.
This operation takes \l{constant time}, because QByteArrayList is
\l{implicitly shared}. This makes returning a QByteArrayList from a
function very fast. If a shared instance is modified, it will be
copied (copy-on-write), and that takes \l{linear time}.
\sa operator=()
*/
/*!
\fn QByteArrayList::QByteArrayList(QList<QByteArray> &&other)
\overload
Move-constructs from \a other.
This constructor is only enabled if the compiler supports C++11
move semantics.
\sa operator=()
*/
/*! \fn QByteArrayList::QByteArrayList(std::initializer_list<QByteArray> args)
Constructs a list from a std::initializer_list given by \a args.
This constructor is only enabled if the compiler supports C++11 initializer
lists.
*/
/*!
\fn QByteArrayList &QByteArrayList::operator=(const QList<QByteArray> &other)
Assigns the contents of \a other to this byte array list and returns
a reference to \c *this.
*/
/*!
\fn QByteArrayList &QByteArrayList::operator=(QList<QByteArray> &&other)
\overload
Move-assigns the contents of \a other to this byte array list and returns
a reference to \c *this.
This operator is only enabled if the compiler supports C++11 move
semantics.
*/
/*!
\fn QByteArrayList &QByteArrayList::operator=(std::initializer_list<QByteArray> args)
\overload
Assigns the byte arrays from the initializer_list \a args to this byte array
list and returns a reference to \c *this.
This operator is only enabled if the compiler supports C++11 initializer
lists.
*/
/*!
\fn QByteArray QByteArrayList::join() const
@ -235,60 +152,4 @@ QByteArray QtPrivate::QByteArrayList_join(const QByteArrayList *that, const char
return res;
}
/*!
\fn QByteArrayList operator+(const QByteArrayList &list1, const QByteArrayList &list2)
\fn QByteArrayList operator+(const QByteArrayList &list1, const QList<QByteArray> &list2)
\fn QByteArrayList operator+(const QList<QByteArray> &list1, const QByteArrayList &list2)
\fn QByteArrayList operator+(QByteArrayList &&list1, const QByteArrayList &list2)
\fn QByteArrayList operator+(QByteArrayList &&list1, const QList<QByteArray> &list2)
\relates QByteArrayList
Returns a byte array list that is the concatenation of \a list1 and \a list2.
*/
/*!
\fn QByteArrayList& operator+=(QByteArrayList &list1, const QList<QByteArray> &list2)
\relates QByteArrayList
Appends \a list2 (which may be a QByteArrayList itself) to \a
list1 and returns a reference to \a list1.
*/
/*!
\fn QByteArrayList &QByteArrayList::operator<<(const QByteArray &ba)
Appends the given byte array, \a ba, to this byte array list and returns
a reference to the byte array list.
\sa append()
*/
/*!
\fn QByteArrayList &QByteArrayList::operator<<(const QList<QByteArray> &other)
\overload
Appends the list of byte arrays \a other (which may be a
QByteArrayList itself) to this byte array list and returns a
reference to \c *this. */
/*!
\fn QDataStream &operator>>(QDataStream &in, QByteArrayList &list)
\relates QByteArrayList
Reads a byte array list from the given \a in stream into the specified
\a list.
\sa {Serializing Qt Data Types}
*/
/*!
\fn QDataStream &operator<<(QDataStream &out, const QByteArrayList &list)
\relates QByteArrayList
Writes the given byte array \a list to the specified \a out stream.
\sa {Serializing Qt Data Types}
*/
QT_END_NAMESPACE

View File

@ -40,146 +40,41 @@
**
****************************************************************************/
#include <QtCore/qlist.h>
#ifndef QBYTEARRAYLIST_H
#define QBYTEARRAYLIST_H
#include <QtCore/qdatastream.h>
#include <QtCore/qlist.h>
#include <QtCore/qbytearray.h>
QT_BEGIN_NAMESPACE
typedef QListIterator<QByteArray> QByteArrayListIterator;
typedef QMutableListIterator<QByteArray> QMutableByteArrayListIterator;
class QByteArrayList : public QList<QByteArray>
{
public:
QByteArrayList() { }
explicit QByteArrayList(const QByteArray &i) { append(i); }
QByteArrayList(const QList<QByteArray> &l) : QList<QByteArray>(l) { }
#ifdef Q_COMPILER_RVALUE_REFS
QByteArrayList(QList<QByteArray> &&l) : QList<QByteArray>(qMove(l)) { }
#endif
#ifdef Q_COMPILER_INITIALIZER_LISTS
QByteArrayList(std::initializer_list<QByteArray> args) : QList<QByteArray>(args) { }
#endif
// compiler-generated copy/move ctor/assignment operators are ok
// compiler-generated dtor is ok
// inherited swap() is ok (sic!)
// For the operators, we could just say using QList<QByteArray>::operator{=,<<},
// but they would not return QByteArrayList&, so we need to write inline forwarders:
QByteArrayList &operator=(const QList<QByteArray> &other)
{ QList<QByteArray>::operator=(other); return *this; }
#ifdef Q_COMPILER_RVALUE_REFS
QByteArrayList &operator=(QList<QByteArray> &&other)
{ QList<QByteArray>::operator=(qMove(other)); return *this; }
#endif
// if this is missing, assignment from an initializer_list is ambiguous:
#ifdef Q_COMPILER_INITIALIZER_LISTS
QByteArrayList &operator=(std::initializer_list<QByteArray> args)
{ QByteArrayList copy(args); swap(copy); return *this; }
#endif
QByteArrayList &operator<<(const QByteArray &str)
{ QList<QByteArray>::operator<<(str); return *this; }
QByteArrayList &operator<<(const QList<QByteArray> &l)
{ QList<QByteArray>::operator<<(l); return *this; }
//
// actual functionality provided on top of what QList<QByteArray> provides starts here:
//
inline QByteArray join() const;
inline QByteArray join(const QByteArray &sep) const;
inline QByteArray join(char sep) const;
};
Q_DECLARE_TYPEINFO(QByteArrayList, Q_MOVABLE_TYPE);
typedef QList<QByteArray> QByteArrayList;
namespace QtPrivate {
QByteArray Q_CORE_EXPORT QByteArrayList_join(const QByteArrayList *that, const char *separator, int separatorLength);
}
inline QByteArray QByteArrayList::join() const
{
return QtPrivate::QByteArrayList_join(this, 0, 0);
}
inline QByteArray QByteArrayList::join(const QByteArray &sep) const
{
return QtPrivate::QByteArrayList_join(this, sep.constData(), sep.size());
}
inline QByteArray QByteArrayList::join(char sep) const
{
return QtPrivate::QByteArrayList_join(this, &sep, 1);
}
inline QByteArrayList operator+(const QByteArrayList &lhs, const QByteArrayList &rhs)
{
QByteArrayList res = lhs;
res += rhs;
return res;
}
#ifdef Q_COMPILER_RVALUE_REFS
inline QByteArrayList operator+(QByteArrayList &&lhs, const QByteArrayList &rhs)
{
lhs += rhs;
return qMove(lhs);
}
#ifdef Q_QDOC
class QByteArrayList : public QList<QByteArray>
#else
template <> struct QListSpecialMethods<QByteArray>
#endif
{
inline QByteArray join() const
{ return QtPrivate::QByteArrayList_join(self(), 0, 0); }
inline QByteArray join(const QByteArray &sep) const
{ return QtPrivate::QByteArrayList_join(self(), sep.constData(), sep.size()); }
inline QByteArray join(char sep) const
{ return QtPrivate::QByteArrayList_join(self(), &sep, 1); }
inline QByteArrayList operator+(const QByteArrayList &lhs, const QList<QByteArray> &rhs)
{
QByteArrayList res = lhs;
res += rhs;
return res;
}
#ifdef Q_COMPILER_RVALUE_REFS
inline QByteArrayList operator+(QByteArrayList &&lhs, const QList<QByteArray> &rhs)
{
lhs += rhs;
return qMove(lhs);
}
#endif
inline QByteArrayList operator+(const QList<QByteArray> &lhs, const QByteArrayList &rhs)
{
QByteArrayList res = lhs;
res += rhs;
return res;
}
#if 0 // ambiguous with QList<QByteArray>::operator+(const QList<QByteArray> &) const
#ifdef Q_COMPILER_RVALUE_REFS
inline QByteArrayList operator+(QList<QByteArray> &&lhs, const QByteArrayList &rhs)
{
lhs += rhs;
return qMove(lhs);
}
#endif
#endif
inline QByteArrayList& operator+=(QByteArrayList &lhs, const QList<QByteArray> &rhs)
{
lhs.append(rhs);
return lhs;
}
#ifndef QT_NO_DATASTREAM
inline QDataStream &operator>>(QDataStream &in, QByteArrayList &list)
{
return operator>>(in, static_cast<QList<QByteArray> &>(list));
}
inline QDataStream &operator<<(QDataStream &out, const QByteArrayList &list)
{
return operator<<(out, static_cast<const QList<QByteArray> &>(list));
}
#endif // QT_NO_DATASTREAM
private:
typedef QList<QByteArray> Self;
Self *self() { return static_cast<Self *>(this); }
const Self *self() const { return static_cast<const Self *>(this); }
};
QT_END_NAMESPACE

View File

@ -476,6 +476,11 @@ void **QListData::erase(void **xi)
value that might not be in the valid range, check that it is less
than the value returned by size() but \e not less than 0.
\section1 More members
If T is a QByteArray, this class has a couple more members that can be
used. See the documentation for QByteArrayList for more information.
\sa QListIterator, QMutableListIterator, QLinkedList, QVector
*/

View File

@ -70,6 +70,9 @@ QT_BEGIN_NAMESPACE
template <typename T> class QVector;
template <typename T> class QSet;
template <typename T> struct QListSpecialMethods { };
template <> struct QListSpecialMethods<QByteArray>;
struct Q_CORE_EXPORT QListData {
struct Data {
QtPrivate::RefCount ref;
@ -102,7 +105,7 @@ struct Q_CORE_EXPORT QListData {
};
template <typename T>
class QList
class QList : public QListSpecialMethods<T>
{
struct Node { void *v;
#if defined(Q_CC_BOR)
@ -745,7 +748,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper()
template <typename T>
Q_OUTOFLINE_TEMPLATE QList<T>::QList(const QList<T> &l)
: d(l.d)
: QListSpecialMethods<T>(l), d(l.d)
{
if (!d->ref.ref()) {
p.detach(d->alloc);
@ -952,6 +955,8 @@ Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(List)
QT_END_NAMESPACE
#include <QtCore/qbytearraylist.h>
#ifdef Q_CC_MSVC
#pragma warning( pop )
#endif

View File

@ -81,7 +81,7 @@ void tst_QByteArrayList::join_data() const
QTest::newRow("data1") << QByteArrayList()
<< QByteArray();
QTest::newRow("data2") << QByteArrayList("one")
QTest::newRow("data2") << (QByteArrayList() << "one")
<< QByteArray("one");
QTest::newRow("data3") << (QByteArrayList() << "a" << "b")
@ -114,7 +114,7 @@ void tst_QByteArrayList::joinByteArray_data() const
<< QByteArray("separator")
<< QByteArray();
QTest::newRow("data3") << QByteArrayList("one")
QTest::newRow("data3") << (QByteArrayList() << "one")
<< QByteArray("separator")
<< QByteArray("one");