Long live std::pair!

Make QPair an alias for std::pair, and qMakePair just a forwarder
towards std::make_pair.

Why? Fundamentally to ditch a bunch of NIH code; gain for free
structured bindings, std::tuple and std::reference_wrapper
compatibility, and so on.

Breakages:

* Some that code manually forward declares QPair.
We don't care about it (<QContainerFwd> is the proper way).

* Some code that overloads on std::pair and QPair. Luckily
it's mostly centralized: debug, metatypes, testing macros.
Just remove the QPair overload.

* Usages of qMakePair forcing the template type parameters.
There are a handful of these in qtbase, but only one was actually
broken.

* std::pair is NOT (and will never likely be) trivially copiable.
This is agreed to be a mistake done by practically all implementations
in C++11, can can't be fixed without breaking ABI.
Some code using QPair assuming it's trivially copiable may break;
exactly one occurrence was in qtbase.

* QMetaType logic extracts the type names in two different ways,
one by looking at the source code string (e.g. extracted by moc)
and one via some ad-hoc reflection in C++. We need to make
"QPair" (as spelled in the source code) be the same as "std::pair"
(gathered via reflection, which will see through the alias)
when compared. The way it's already done e.g. for QList is
by actually replacing the moc-extracted name with the name
of the actual type used in C++; do the same here.
On libc++, std::pair is actually in an inline namespace --
i.e. std::__1::pair; the reflection will extract and store
"std::__1::pair" so we need an ad-hoc fix to QMetaType.

[ChangeLog][QtCore][QPair] QPair is now an alias to std::pair,
and does not exist as a class in Qt any more. This may break
code such as functions overloaded for both QPair and std::pair.
Usually, the overload taking a QPair can be safely discarded,
leaving only the one taking a std::pair. QPair API has not changed,
and qMakePair is still available for compatibility (although
new code is encouraged to use std::pair and std::make_pair
directly instead).

Change-Id: I7725c751bf23946cde577b1406e86a336c0a3dcf
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
bb10
Giuseppe D'Angelo 2020-02-15 00:11:22 +01:00
parent ce5931aaf2
commit 8e98a161e9
28 changed files with 95 additions and 502 deletions

View File

@ -1,75 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qmath.h>
//! [0]
QPair<QString, double> pair;
//! [0]
//! [1]
pair.first = "pi";
pair.second = M_PI;
//! [1]
//! [struct]
struct Variable {
QString name;
double value;
};
Variable v;
v.name = "pi";
v.value = M_PI;
//! [struct]
//! [2]
QList<QPair<int, double> > list;
list.append(qMakePair(66, M_PI));
//! [2]

View File

@ -608,8 +608,6 @@
\li QContiguousCache<T> provides an efficient way of caching data
that is typically accessed in a contiguous way.
\li QPair<T1, T2> stores a pair of elements.
\endlist
Additional non-template types that compete with Qt's template

View File

@ -45,7 +45,6 @@
#include <QtCore/qhash.h>
#include <QtCore/qlist.h>
#include <QtCore/qmap.h>
#include <QtCore/qpair.h>
#include <QtCore/qtextstream.h>
#include <QtCore/qstring.h>
#include <QtCore/qvector.h>
@ -318,15 +317,6 @@ inline QDebug operator<<(QDebug debug, const QMultiHash<Key, T> &hash)
return QtPrivate::printAssociativeContainer(debug, "QMultiHash", hash);
}
template <class T1, class T2>
inline QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair)
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << "QPair(" << pair.first << ',' << pair.second << ')';
debug.setAutoInsertSpaces(oldSetting);
return debug.maybeSpace();
}
template <class T1, class T2>
inline QDebug operator<<(QDebug debug, const std::pair<T1, T2> &pair)
{

View File

@ -240,8 +240,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(F) \
F(QHash, class) \
F(QMap, class) \
F(QPair, struct)
F(QMap, class)
#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(F) \
F(QSharedPointer) \
@ -1391,15 +1390,6 @@ QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QPairVariantInterfaceImpl, Q_MOVABLE_TYPE)
template<typename From>
struct QPairVariantInterfaceConvertFunctor;
template<typename T, typename U>
struct QPairVariantInterfaceConvertFunctor<QPair<T, U> >
{
QPairVariantInterfaceImpl operator()(const QPair<T, U>& f) const
{
return QPairVariantInterfaceImpl(&f);
}
};
template<typename T, typename U>
struct QPairVariantInterfaceConvertFunctor<std::pair<T, U> >
{
@ -1670,8 +1660,6 @@ namespace QtPrivate
}
};
template<typename T, typename U>
struct IsPair<QPair<T, U> > : IsMetaTypePair<QPair<T, U> > {};
template<typename T, typename U>
struct IsPair<std::pair<T, U> > : IsMetaTypePair<std::pair<T, U> > {};
template<typename T>
@ -2209,7 +2197,6 @@ Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QHash)
Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QMap)
Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(std::map)
Q_DECLARE_METATYPE_TEMPLATE_2ARG(QPair)
Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::pair)
#define Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER(TEMPLATENAME) \
@ -2532,6 +2519,16 @@ public:
// Replace QList by QVector
appendStr("QVector");
}
if (skipToken(begin, end, "QPair")) {
// replace QPair by std::pair
#ifdef _LIBCPP_VERSION
appendStr("std::" QT_STRINGIFY(_LIBCPP_ABI_NAMESPACE) "::pair");
#else
appendStr("std::pair");
#endif
}
if (!hasMiddleConst) {
// Normalize the integer types
int numLong = 0;

View File

@ -1119,6 +1119,16 @@ int QDataStream::readRawData(char *s, int len)
return readBlock(s, len);
}
/*! \fn template <class T1, class T2> QDataStream &operator>>(QDataStream &in, std::pair<T1, T2> &pair)
\since 6.0
\relates QDataStream
Reads a pair from stream \a in into \a pair.
This function requires the T1 and T2 types to implement \c operator>>().
\sa {Serializing Qt Data Types}
*/
/*****************************************************************************
QDataStream write functions
@ -1446,6 +1456,18 @@ int QDataStream::skipRawData(int len)
return skipResult;
}
/*!
\fn template <class T1, class T2> QDataStream &operator<<(QDataStream &out, const std::pair<T1, T2> &pair)
\since 6.0
\relates QDataStream
Writes the pair \a pair to stream \a out.
This function requires the T1 and T2 types to implement \c operator<<().
\sa {Serializing Qt Data Types}
*/
QT_END_NAMESPACE
#endif // QT_NO_DATASTREAM

View File

@ -480,14 +480,14 @@ inline QDataStream &operator<<(QDataStream &s, const QMultiMap<Key, T> &map)
#ifndef QT_NO_DATASTREAM
template <class T1, class T2>
inline QDataStream& operator>>(QDataStream& s, QPair<T1, T2>& p)
inline QDataStream& operator>>(QDataStream& s, std::pair<T1, T2> &p)
{
s >> p.first >> p.second;
return s;
}
template <class T1, class T2>
inline QDataStream& operator<<(QDataStream& s, const QPair<T1, T2>& p)
inline QDataStream& operator<<(QDataStream& s, const std::pair<T1, T2> &p)
{
s << p.first << p.second;
return s;

View File

@ -50,7 +50,8 @@ template <class Key, class T> class QHash;
template <class Key, class T> class QMap;
template <class Key, class T> class QMultiHash;
template <class Key, class T> class QMultiMap;
template <class T1, class T2> struct QPair;
template <typename T1, typename T2>
using QPair = std::pair<T1, T2>;
template <class T> class QQueue;
template <class T> class QSet;
template <class T> class QStack;

View File

@ -252,15 +252,6 @@ inline size_t qHashRangeCommutative(InputIterator first, InputIterator last, siz
return std::accumulate(first, last, seed, QtPrivate::QHashCombineCommutative());
}
template <typename T1, typename T2> inline size_t qHash(const QPair<T1, T2> &key, size_t seed = 0)
noexcept(noexcept(qHash(key.first, seed)) && noexcept(qHash(key.second, seed)))
{
QtPrivate::QHashCombine hash;
seed = hash(seed, key.first);
seed = hash(seed, key.second);
return seed;
}
template <typename T1, typename T2> inline size_t qHash(const std::pair<T1, T2> &key, size_t seed = 0)
noexcept(noexcept(qHash(key.first, seed)) && noexcept(qHash(key.second, seed)))
{

View File

@ -44,115 +44,22 @@
QT_BEGIN_NAMESPACE
template <class T1, class T2>
struct QPair
{
typedef T1 first_type;
typedef T2 second_type;
Q_DECL_CONSTEXPR QPair()
noexcept((std::is_nothrow_default_constructible<T1>::value &&
std::is_nothrow_default_constructible<T2>::value))
: first(), second() {}
Q_DECL_CONSTEXPR QPair(const T1 &t1, const T2 &t2)
noexcept((std::is_nothrow_copy_constructible<T1>::value &&
std::is_nothrow_copy_constructible<T2>::value))
: first(t1), second(t2) {}
// compiler-generated copy/move ctor/assignment operators are fine!
template <typename TT1, typename TT2>
Q_DECL_CONSTEXPR QPair(const QPair<TT1, TT2> &p)
noexcept((std::is_nothrow_constructible<T1, TT1&>::value &&
std::is_nothrow_constructible<T2, TT2&>::value))
: first(p.first), second(p.second) {}
template <typename TT1, typename TT2>
Q_DECL_RELAXED_CONSTEXPR QPair &operator=(const QPair<TT1, TT2> &p)
noexcept((std::is_nothrow_assignable<T1, TT1&>::value &&
std::is_nothrow_assignable<T2, TT2&>::value))
{ first = p.first; second = p.second; return *this; }
template <typename TT1, typename TT2>
Q_DECL_CONSTEXPR QPair(QPair<TT1, TT2> &&p)
noexcept((std::is_nothrow_constructible<T1, TT1>::value &&
std::is_nothrow_constructible<T2, TT2>::value))
// can't use std::move here as it's not constexpr in C++11:
: first(static_cast<TT1 &&>(p.first)), second(static_cast<TT2 &&>(p.second)) {}
template <typename TT1, typename TT2>
Q_DECL_RELAXED_CONSTEXPR QPair &operator=(QPair<TT1, TT2> &&p)
noexcept((std::is_nothrow_assignable<T1, TT1>::value &&
std::is_nothrow_assignable<T2, TT2>::value))
{ first = std::move(p.first); second = std::move(p.second); return *this; }
Q_DECL_RELAXED_CONSTEXPR void swap(QPair &other)
noexcept(noexcept(qSwap(other.first, other.first)) && noexcept(qSwap(other.second, other.second)))
{
// use qSwap() to pick up ADL swaps automatically:
qSwap(first, other.first);
qSwap(second, other.second);
}
T1 first;
T2 second;
};
#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606
template<class T1, class T2>
QPair(T1, T2) -> QPair<T1, T2>;
#if 0
#pragma qt_class(QPair)
#endif
template <typename T1, typename T2>
void swap(QPair<T1, T2> &lhs, QPair<T1, T2> &rhs) noexcept(noexcept(lhs.swap(rhs)))
{ lhs.swap(rhs); }
using QPair = std::pair<T1, T2>;
template <typename T1, typename T2>
constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2)
noexcept(noexcept(std::make_pair(std::forward<T1>(value1), std::forward<T2>(value2))))
{
return std::make_pair(std::forward<T1>(value1), std::forward<T2>(value2));
}
// mark QPair<T1,T2> as complex/movable/primitive depending on the
// typeinfos of the constituents:
template<class T1, class T2>
class QTypeInfo<QPair<T1, T2> > : public QTypeInfoMerger<QPair<T1, T2>, T1, T2> {}; // Q_DECLARE_TYPEINFO
template <class T1, class T2>
Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator==(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
noexcept(noexcept(p1.first == p2.first && p1.second == p2.second))
{ return p1.first == p2.first && p1.second == p2.second; }
template <class T1, class T2>
Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator!=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
noexcept(noexcept(!(p1 == p2)))
{ return !(p1 == p2); }
template <class T1, class T2>
Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator<(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
noexcept(noexcept(p1.first < p2.first || (!(p2.first < p1.first) && p1.second < p2.second)))
{
return p1.first < p2.first || (!(p2.first < p1.first) && p1.second < p2.second);
}
template <class T1, class T2>
Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator>(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
noexcept(noexcept(p2 < p1))
{
return p2 < p1;
}
template <class T1, class T2>
Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator<=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
noexcept(noexcept(!(p2 < p1)))
{
return !(p2 < p1);
}
template <class T1, class T2>
Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator>=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
noexcept(noexcept(!(p1 < p2)))
{
return !(p1 < p2);
}
template <class T1, class T2>
Q_DECL_CONSTEXPR Q_OUTOFLINE_TEMPLATE QPair<T1, T2> qMakePair(const T1 &x, const T2 &y)
noexcept(noexcept(QPair<T1, T2>(x, y)))
{
return QPair<T1, T2>(x, y);
}
class QTypeInfo<std::pair<T1, T2>> : public QTypeInfoMerger<std::pair<T1, T2>, T1, T2> {};
QT_END_NAMESPACE

View File

@ -28,255 +28,24 @@
/*!
\class QPair
\inmodule QtCore
\reentrant
\brief The QPair class is a template class that stores a pair of items.
\obsolete
\brief QPair is an alias for std::pair.
\ingroup tools
QPair\<T1, T2\> can be used in your application if the STL \c
pair type is not available. It stores one value of type T1 and
one value of type T2. It can be used as a return value for a
function that needs to return two values, or as the value type of
a \l{Container classes}{generic container}.
Here's an example of a QPair that stores one QString and one \c
double value:
\snippet code/doc_src_qpair.cpp 0
The components are accessible as public data members called \l
first and \l second. For example:
\snippet code/doc_src_qpair.cpp 1
Note, however, that it is almost always preferable to define a small struct
to hold the result of a function with multiple return values. A struct
trivially generalizes to more than two values, and allows more descriptive
member names than \c{first} and \c{second}:
\snippet code/doc_src_qpair.cpp struct
The advent of C++11 automatic variable type deduction (\c{auto}) shifts the
emphasis from the type name to the name of functions and members. Thus, QPair,
like \c{std::pair} and \c{std::tuple}, is mostly useful in generic (template)
code, where defining a dedicated type is not possible.
QPair's template data types (T1 and T2) must be \l{assignable
data types}. You cannot, for example, store a QWidget as a value;
instead, store a QWidget *. A few functions have additional
requirements; these requirements are documented on a per-function
basis.
QPair\<T1, T2\> is a typedef for std::pair\<T1, T2\>.
It is provided for backwards compatibility. Use std::pair directly
instead.
\sa {Container Classes}
*/
/*! \typedef QPair::first_type
The type of the first element in the pair (T1).
\sa first
*/
/*! \typedef QPair::second_type
The type of the second element in the pair (T2).
\sa second
*/
/*! \variable QPair::first
The first element in the pair.
*/
/*! \variable QPair::second
The second element in the pair.
*/
/*! \fn template <class T1, class T2> QPair<T1, T2>::QPair()
Constructs an empty pair. The \c first and \c second elements are
initialized with \l{default-constructed value}s.
*/
/*!
\fn template <class T1, class T2> QPair<T1, T2>::QPair(const T1 &value1, const T2 &value2)
Constructs a pair and initializes the \c first element with \a
value1 and the \c second element with \a value2.
\sa qMakePair()
*/
/*!
\fn template <class T1, class T2> void QPair<T1, T2>::swap(QPair &other)
\since 5.5
Swaps this pair with \a other.
Equivalent to
\code
qSwap(this->first, other.first);
qSwap(this->second, other.second);
\endcode
Swap overloads are found in namespace \c std as well as via
argument-dependent lookup (ADL) in the namespace of \c{T} .
*/
/*!
\fn template <class T1, class T2> void swap(QPair<T1, T2> &lhs, QPair<T1, T2> &rhs)
\overload
\relates QPair
\since 5.5
Swaps \a lhs with \a rhs.
*/
/*!
\fn template <class T1, class T2> template <typename TT1, typename TT2> QPair<T1, T2>::QPair(const QPair<TT1, TT2> &p)
\since 5.2
Constructs a pair from the other pair \a p, of types TT1 and TT2. This
constructor will fail if \c first cannot be initialized from \c p.first or
if \c second cannot be initialized from \c p.second.
\sa qMakePair()
*/
/*!
\fn template <class T1, class T2> template <typename TT1, typename TT2> QPair<T1, T2>::QPair(QPair<TT1, TT2> &&p)
\since 5.2
Move-constructs a QPair instance, making it point to the same object that \a p was pointing to.
*/
/*!
\fn template <class T1, class T2> template <typename TT1, typename TT2> QPair & QPair<T1, T2>::operator=(const QPair<TT1, TT2> &p)
\since 5.2
Copies pair \a p into this pair.
\sa qMakePair()
*/
/*!
\fn template <class T1, class T2> template <typename TT1, typename TT2> QPair & QPair<T1, T2>::operator=(QPair<TT1, TT2> &&p)
\since 5.2
Move-assigns pair \a p into this pair instance.
*/
/*! \fn template <class T1, class T2> bool operator==(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
\fn template <class T1, class T2> QPair<T1, T2> qMakePair(T1 &&value1, T2 &&value2)
\obsolete
\relates QPair
Returns \c true if \a p1 is equal to \a p2; otherwise returns \c false.
Two pairs compare equal if their \c first data members compare
equal and if their \c second data members compare equal.
This function requires the T1 and T2 types to have an
implementation of \c operator==().
*/
/*! \fn template <class T1, class T2> bool operator!=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
\relates QPair
Returns \c true if \a p1 is not equal to \a p2; otherwise returns
false. Two pairs compare as not equal if their \c first data
members are not equal or if their \c second data members are not
equal.
This function requires the T1 and T2 types to have an
implementation of \c operator==().
*/
/*! \fn template <class T1, class T2> bool operator<(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
\relates QPair
Returns \c true if \a p1 is less than \a p2; otherwise returns
false. The comparison is done on the \c first members of \a p1
and \a p2; if they compare equal, the \c second members are
compared to break the tie.
This function requires the T1 and T2 types to have an
implementation of \c operator<().
*/
/*! \fn template <class T1, class T2> bool operator>(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
\relates QPair
Returns \c true if \a p1 is greater than \a p2; otherwise returns
false. The comparison is done on the \c first members of \a p1
and \a p2; if they compare equal, the \c second members are
compared to break the tie.
This function requires the T1 and T2 types to have an
implementation of \c operator<().
*/
/*! \fn template <class T1, class T2> bool operator<=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
\relates QPair
Returns \c true if \a p1 is less than or equal to \a p2; otherwise
returns \c false. The comparison is done on the \c first members of
\a p1 and \a p2; if they compare equal, the \c second members are
compared to break the tie.
This function requires the T1 and T2 types to have an
implementation of \c operator<().
*/
/*! \fn template <class T1, class T2> bool operator>=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
\relates QPair
Returns \c true if \a p1 is greater than or equal to \a p2;
otherwise returns \c false. The comparison is done on the \c first
members of \a p1 and \a p2; if they compare equal, the \c second
members are compared to break the tie.
This function requires the T1 and T2 types to have an
implementation of \c operator<().
*/
/*!
\fn template <class T1, class T2> QPair<T1, T2> qMakePair(const T1 &value1, const T2 &value2)
\relates QPair
Returns a QPair\<T1, T2\> that contains \a value1 and \a value2.
Example:
\snippet code/doc_src_qpair.cpp 2
This is equivalent to QPair<T1, T2>(\a value1, \a value2), but
usually requires less typing.
*/
/*! \fn template <class T1, class T2> QDataStream &operator>>(QDataStream &in, QPair<T1, T2> &pair)
\relates QPair
Reads a pair from stream \a in into \a pair.
This function requires the T1 and T2 types to implement \c operator>>().
\sa {Serializing Qt Data Types}
*/
/*! \fn template <class T1, class T2> QDataStream &operator<<(QDataStream &out, const QPair<T1, T2> &pair)
\relates QPair
Writes the pair \a pair to stream \a out.
This function requires the T1 and T2 types to implement \c operator<<().
\sa {Serializing Qt Data Types}
qMakePair forwards its arguments to std::make_pair, and returns
the resulting std::pair. It is provided for backwards compatibility.
Use std::make_pair directly instead.
*/

View File

@ -52,8 +52,6 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_SSL
template <typename A, typename B> struct QPair;
class QIODevice;
class QSslKeyPrivate;

View File

@ -143,11 +143,11 @@ bool QOpenGLTimerQueryPrivate::create()
// Check to see if we also need to resolve the functions for EXT_timer_query
QSurfaceFormat f = context->format();
if (f.version() <= qMakePair<int, int>(3, 2)
if (f.version() <= qMakePair(3, 2)
&& !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query"))
&& context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) {
ext = new QExtTimerQueryHelper(context);
} else if (f.version() <= qMakePair<int, int>(3, 2)
} else if (f.version() <= qMakePair(3, 2)
&& !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query"))
&& !context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) {
qWarning("QOpenGLTimerQuery requires one of:\n"
@ -530,11 +530,11 @@ bool QOpenGLTimeMonitorPrivate::create()
// Check to see if we also need to resolve the functions for EXT_timer_query
QSurfaceFormat f = context->format();
if (f.version() <= qMakePair<int, int>(3, 2)
if (f.version() <= qMakePair(3, 2)
&& !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query"))
&& context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) {
ext = new QExtTimerQueryHelper(context);
} else if (f.version() <= qMakePair<int, int>(3, 2)
} else if (f.version() <= qMakePair(3, 2)
&& !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query"))
&& !context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) {
qWarning("QOpenGLTimeMonitor requires one of:\n"

View File

@ -176,7 +176,7 @@ bool QOpenGLVertexArrayObjectPrivate::create()
vaoFuncsType = NotSupported;
QSurfaceFormat format = ctx->format();
#if !QT_CONFIG(opengles2)
if (format.version() >= qMakePair<int, int>(3,2)) {
if (format.version() >= qMakePair(3,2)) {
vaoFuncs.core_3_2 = QOpenGLVersionFunctionsFactory::get<QOpenGLFunctions_3_2_Core>(ctx);
vaoFuncsType = Core_3_2;
vaoFuncs.core_3_2->glGenVertexArrays(1, &vao);

View File

@ -67,7 +67,7 @@ static SelectionPair querySelection()
QGuiApplication::sendEvent(QGuiApplication::focusObject(), &query);
int anchorPos = query.value(Qt::ImAnchorPosition).toInt();
int cursorPos = query.value(Qt::ImCursorPosition).toInt();
return qMakePair<int, int>(anchorPos, cursorPos);
return qMakePair(anchorPos, cursorPos);
}
static bool hasSelection()

View File

@ -231,14 +231,6 @@ template<> inline char *toString(const QVariant &v)
return qstrdup(vstring.constData());
}
template <typename T1, typename T2>
inline char *toString(const QPair<T1, T2> &pair)
{
const QScopedArrayPointer<char> first(toString(pair.first));
const QScopedArrayPointer<char> second(toString(pair.second));
return toString(QString::asprintf("QPair(%s,%s)", first.data(), second.data()));
}
template <typename T1, typename T2>
inline char *toString(const std::pair<T1, T2> &pair)
{

View File

@ -51,7 +51,6 @@ class QGraphicsItem;
class QPointF;
class QTimeLine;
class QTransform;
template <class T1, class T2> struct QPair;
class QGraphicsItemAnimationPrivate;
class Q_WIDGETS_EXPORT QGraphicsItemAnimation : public QObject

View File

@ -3918,7 +3918,7 @@ QPair<int,int> QTreeViewPrivate::startAndEndColumns(const QRect &rect) const
start = (start == -1 ? 0 : start);
end = (end == -1 ? header->count() - 1 : end);
}
return qMakePair<int,int>(qMin(start, end), qMax(start, end));
return qMakePair(qMin(start, end), qMax(start, end));
}
bool QTreeViewPrivate::hasVisibleChildren(const QModelIndex& parent) const

View File

@ -1381,7 +1381,12 @@ void tst_QMetaObject::normalizedType_data()
QTest::newRow("template6") << "QVector<::Foo::Bar>" << "QVector<::Foo::Bar>";
QTest::newRow("template7") << "QVector<QVector<int> >" << "QVector<QVector<int>>";
QTest::newRow("template8") << "QMap<const int, const short*>" << "QMap<const int,const short*>";
QTest::newRow("template9") << "QPair<const QPair<int, int const *> , QPair<QHash<int, const char*> > >" << "QPair<const QPair<int,const int*>,QPair<QHash<int,const char*>>>";
QTest::newRow("template9") << "QPair<const QPair<int, int const *> , QPair<QHash<int, const char*> > >"
#ifdef _LIBCPP_VERSION
<< "std::__1::pair<const std::__1::pair<int,const int*>,std::__1::pair<QHash<int,const char*>>>";
#else
<< "std::pair<const std::pair<int,const int*>,std::pair<QHash<int,const char*>>>";
#endif
QTest::newRow("template10") << "QList<int const * const> const" << "QVector<const int*const>";
QTest::newRow("template11") << " QSharedPointer<QVarLengthArray< QString const, ( 16>> 2 )> > const & "
<< "QSharedPointer<QVarLengthArray<const QString,(16>>2)>>";

View File

@ -1640,7 +1640,7 @@ void tst_QMetaType::automaticTemplateRegistration()
QCOMPARE(QVariant::fromValue(intIntPair).value<IntIntPair>().second, 2);
}
{
IntUIntPair intUIntPair = qMakePair<int, uint>(4, 2);
IntUIntPair intUIntPair = qMakePair(4, 2u);
QCOMPARE(QVariant::fromValue(intUIntPair).value<IntUIntPair>().first, 4);
QCOMPARE(QVariant::fromValue(intUIntPair).value<IntUIntPair>().second, (uint)2);
}
@ -1727,7 +1727,7 @@ void tst_QMetaType::automaticTemplateRegistration()
#define FOR_EACH_2ARG_TEMPLATE_TYPE(F, RealName1, RealName2) \
F(QHash, RealName1, RealName2) \
F(QMap, RealName1, RealName2) \
F(QPair, RealName1, RealName2)
F(std::pair, RealName1, RealName2)
#define PRINT_2ARG_TEMPLATE_INTERNAL(RealName1, RealName2) \
FOR_EACH_2ARG_TEMPLATE_TYPE(CREATE_AND_VERIFY_CONTAINER, RealName1, RealName2)
@ -1753,7 +1753,7 @@ void tst_QMetaType::automaticTemplateRegistration()
CREATE_AND_VERIFY_CONTAINER(QVector, void*)
CREATE_AND_VERIFY_CONTAINER(QVector, const void*)
CREATE_AND_VERIFY_CONTAINER(QList, void*)
CREATE_AND_VERIFY_CONTAINER(QPair, void*, void*)
CREATE_AND_VERIFY_CONTAINER(std::pair, void*, void*)
CREATE_AND_VERIFY_CONTAINER(QHash, void*, void*)
CREATE_AND_VERIFY_CONTAINER(QHash, const void*, const void*)

View File

@ -3,5 +3,4 @@ TARGET = tst_qpair
QT = core testlib
SOURCES = tst_qpair.cpp
# Force C++17 if available (needed due to Q_COMPILER_DEDUCTION_GUIDES)
contains(QT_CONFIG, c++1z): CONFIG += c++1z
contains(QT_CONFIG, c++2a): CONFIG += c++2a

View File

@ -39,7 +39,7 @@ private Q_SLOTS:
void testConstexpr();
void testConversions();
void taskQTBUG_48780_pairContainingCArray();
void testDeducationRules();
void testDeductionRules();
};
class C { C() {} char _[4]; };
@ -203,9 +203,9 @@ void tst_QPair::taskQTBUG_48780_pairContainingCArray()
Q_UNUSED(pair);
}
void tst_QPair::testDeducationRules()
void tst_QPair::testDeductionRules()
{
#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606
#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201907L
QPair p1{1, 2};
static_assert(std::is_same<decltype(p1)::first_type, decltype(1)>::value);
static_assert(std::is_same<decltype(p1)::second_type, decltype(2)>::value);
@ -224,7 +224,7 @@ void tst_QPair::testDeducationRules()
QCOMPARE(p3.first, "string");
QCOMPARE(p3.second, 2);
#else
QSKIP("Unsupported");
QSKIP("Unsupported (requires C++20's CTAD for aliases)");
#endif
}

View File

@ -82,7 +82,7 @@ void tst_QAuthenticator::basicAuth()
QCOMPARE(priv->phase, QAuthenticatorPrivate::Start);
QList<QPair<QByteArray, QByteArray> > headers;
headers << qMakePair<QByteArray, QByteArray>(QByteArray("WWW-Authenticate"), "Basic " + data.toUtf8());
headers << qMakePair(QByteArray("WWW-Authenticate"), "Basic " + data.toUtf8());
priv->parseHttpResponse(headers, /*isProxy = */ false);
QCOMPARE(auth.realm(), realm);
@ -130,7 +130,7 @@ void tst_QAuthenticator::ntlmAuth()
// This phase of NTLM contains no information, other than what we're willing to negotiate
// Current implementation uses flags:
// NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_REQUEST_TARGET
headers << qMakePair<QByteArray, QByteArray>("WWW-Authenticate", "NTLM");
headers << qMakePair(QByteArrayLiteral("WWW-Authenticate"), QByteArrayLiteral("NTLM"));
priv->parseHttpResponse(headers, /*isProxy = */ false);
if (sso)
QVERIFY(priv->calculateResponse("GET", "/", "").startsWith("NTLM "));
@ -139,7 +139,7 @@ void tst_QAuthenticator::ntlmAuth()
// NTLM phase 2: challenge
headers.clear();
headers << qMakePair<QByteArray, QByteArray>(QByteArray("WWW-Authenticate"), "NTLM " + data.toUtf8());
headers << qMakePair(QByteArray("WWW-Authenticate"), "NTLM " + data.toUtf8());
priv->parseHttpResponse(headers, /*isProxy = */ false);
QEXPECT_FAIL("with-realm", "NTLM authentication code doesn't extract the realm", Continue);

View File

@ -8,8 +8,8 @@
<testcase result="pass" name="initTestCase"/>
<testcase result="fail" name="testQPair">
<failure message="Compared values are not the same
Actual (pair1): &quot;QPair(1,1)&quot;
Expected (pair2): &quot;QPair(1,2)&quot;" result="fail"/>
Actual (pair1): &quot;std::pair(1,1)&quot;
Expected (pair2): &quot;std::pair(1,2)&quot;" result="fail"/>
</testcase>
<testcase result="fail" name="testStdPair">
<failure message="Compared values are not the same

View File

@ -10,8 +10,8 @@
<TestFunction name="testQPair">
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp" line="0">
<Description><![CDATA[Compared values are not the same
Actual (pair1): "QPair(1,1)"
Expected (pair2): "QPair(1,2)"]]></Description>
Actual (pair1): "std::pair(1,1)"
Expected (pair2): "std::pair(1,2)"]]></Description>
</Incident>
<Duration msecs="0"/>
</TestFunction>

View File

@ -5,10 +5,10 @@ not ok 2 - testQPair()
---
type: QCOMPARE
message: Compared values are not the same
wanted: "QPair(1,2)" (pair2)
found: "QPair(1,1)" (pair1)
expected: "QPair(1,2)" (pair2)
actual: "QPair(1,1)" (pair1)
wanted: "std::pair(1,2)" (pair2)
found: "std::pair(1,1)" (pair1)
expected: "std::pair(1,2)" (pair2)
actual: "std::pair(1,1)" (pair1)
at: tst_PairDiagnostics::testQPair() (qtbase/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp:51)
file: qtbase/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp
line: 51

View File

@ -2,7 +2,7 @@
##teamcity[testStarted name='initTestCase()' flowId='tst_PairDiagnostics']
##teamcity[testFinished name='initTestCase()' flowId='tst_PairDiagnostics']
##teamcity[testStarted name='testQPair()' flowId='tst_PairDiagnostics']
##teamcity[testFailed name='testQPair()' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp(0)|]' details='Compared values are not the same|n Actual (pair1): "QPair(1,1)"|n Expected (pair2): "QPair(1,2)"' flowId='tst_PairDiagnostics']
##teamcity[testFailed name='testQPair()' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp(0)|]' details='Compared values are not the same|n Actual (pair1): "std::pair(1,1)"|n Expected (pair2): "std::pair(1,2)"' flowId='tst_PairDiagnostics']
##teamcity[testFinished name='testQPair()' flowId='tst_PairDiagnostics']
##teamcity[testStarted name='testStdPair()' flowId='tst_PairDiagnostics']
##teamcity[testFailed name='testStdPair()' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp(0)|]' details='Compared values are not the same|n Actual (pair1): "std::pair(1,1)"|n Expected (pair2): "std::pair(1,2)"' flowId='tst_PairDiagnostics']

View File

@ -2,8 +2,8 @@
Config: Using QtTest library
PASS : tst_PairDiagnostics::initTestCase()
FAIL! : tst_PairDiagnostics::testQPair() Compared values are not the same
Actual (pair1): "QPair(1,1)"
Expected (pair2): "QPair(1,2)"
Actual (pair1): "std::pair(1,1)"
Expected (pair2): "std::pair(1,2)"
Loc: [qtbase/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp(0)]
FAIL! : tst_PairDiagnostics::testStdPair() Compared values are not the same
Actual (pair1): "std::pair(1,1)"

View File

@ -12,8 +12,8 @@
<TestFunction name="testQPair">
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp" line="0">
<Description><![CDATA[Compared values are not the same
Actual (pair1): "QPair(1,1)"
Expected (pair2): "QPair(1,2)"]]></Description>
Actual (pair1): "std::pair(1,1)"
Expected (pair2): "std::pair(1,2)"]]></Description>
</Incident>
<Duration msecs="0"/>
</TestFunction>