From eb9c8042cfa71f16cda27cdeb052d84a6cc117d7 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 14 Mar 2023 16:23:31 +0100 Subject: [PATCH] Short live QT_ENABLE_P0846_SEMANTICS_FOR! In C++17, unqualified lookup doesn't find function templates that require ADL from a call with explicit template arguments, unless another function template of that name is in scope (otherwise, the < is parsed as operator less-than instead). P0846, merged for C++20, fixes this to repeat the name lookup, parsing the < as indicating a template. We have API in Qt (Tuple Protocol for some types, e.g. QPoint) that work for the purpose of Structured Bindings, but don't work for manual unqualified calls when P0846 semantics are missing, and we're adding more, to QVariant, so add a macro to handle the issue. The macro simply declares a function template overload of the given name for a throw-away struct, thereby bringing, for that one name, P0846 semantics into C++17. When we require C++20, we can drop this again. Amends: - fb6b7869e8bdda94f7e791db7f281f3bb6e0e004 for QPoint(F) - 8ae9431c792f14a32909ac013a1383547d6bcfa8 for QMargins(F) - 0e22001a3bb070d4e9956e89543ec0e5ac6f23f8 for the rest [ChangeLog][QtCore][QSize/F, QMargins/F, QPoint/F] Fixed manual get() calls (Tuple Protocol) in C++17 mode. Task-number: QTBUG-111598 Change-Id: I2ffaef12c5bb6d82f75ce78a7c03c6789dfa0691 Reviewed-by: Fabian Kosmale Reviewed-by: Giuseppe D'Angelo --- src/corelib/global/qcompilerdetection.h | 14 +++++++++ src/corelib/tools/qmargins.h | 2 ++ src/corelib/tools/qpoint.h | 2 ++ src/corelib/tools/qsize.h | 2 ++ .../corelib/tools/qmargins/tst_qmargins.cpp | 29 +++++++++++++++++++ .../auto/corelib/tools/qpoint/tst_qpoint.cpp | 22 ++++++++++++++ .../corelib/tools/qpointf/tst_qpointf.cpp | 22 ++++++++++++++ tests/auto/corelib/tools/qsize/tst_qsize.cpp | 22 ++++++++++++++ .../auto/corelib/tools/qsizef/tst_qsizef.cpp | 22 ++++++++++++++ 9 files changed, 137 insertions(+) diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index cbea1a80248..5baa69270e5 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1358,6 +1358,20 @@ QT_WARNING_DISABLE_MSVC(4530) /* C++ exception handler used, but unwind semantic # endif #endif +#if __cplusplus >= 202002L // P0846 doesn't have a feature macro :/ +# define QT_COMPILER_HAS_P0846 +#endif + +#ifdef QT_COMPILER_HAS_P0846 +# define QT_ENABLE_P0846_SEMANTICS_FOR(func) +#else + class QT_CLASS_JUST_FOR_P0846_SIMULATION; +# define QT_ENABLE_P0846_SEMANTICS_FOR(func) \ + template \ + void func (QT_CLASS_JUST_FOR_P0846_SIMULATION *); \ + /* end */ +#endif // !P0846 + #endif // __cplusplus #endif // QCOMPILERDETECTION_H diff --git a/src/corelib/tools/qmargins.h b/src/corelib/tools/qmargins.h index 0b4f74e9dd5..f8d7150dfdc 100644 --- a/src/corelib/tools/qmargins.h +++ b/src/corelib/tools/qmargins.h @@ -11,6 +11,8 @@ QT_BEGIN_NAMESPACE +QT_ENABLE_P0846_SEMANTICS_FOR(get) + class QMarginsF; /***************************************************************************** diff --git a/src/corelib/tools/qpoint.h b/src/corelib/tools/qpoint.h index 425948966dd..7df4d490058 100644 --- a/src/corelib/tools/qpoint.h +++ b/src/corelib/tools/qpoint.h @@ -15,6 +15,8 @@ struct CGPoint; QT_BEGIN_NAMESPACE +QT_ENABLE_P0846_SEMANTICS_FOR(get) + class QPointF; class QPoint diff --git a/src/corelib/tools/qsize.h b/src/corelib/tools/qsize.h index dac2a48908b..a5eaf34afe6 100644 --- a/src/corelib/tools/qsize.h +++ b/src/corelib/tools/qsize.h @@ -17,6 +17,8 @@ struct CGSize; QT_BEGIN_NAMESPACE +// QT_ENABLE_P0846_SEMANTICS_FOR(get) // from qmargins.h + class QSizeF; class Q_CORE_EXPORT QSize diff --git a/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp b/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp index c99b3d6e336..4b49d152a35 100644 --- a/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp +++ b/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp @@ -1,6 +1,35 @@ // Copyright (C) 2022 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +#include +#ifdef QVARIANT_H +# error "This test requires qmargins.h to not include qvariant.h" +#endif + +// don't assume +template +constexpr inline bool my_is_same_v = false; +template +constexpr inline bool my_is_same_v = true; + +#define CHECK(cvref) \ + static_assert(my_is_same_v(std::declval())), int cvref >); \ + static_assert(my_is_same_v(std::declval())), int cvref >); \ + static_assert(my_is_same_v(std::declval())), int cvref >); \ + static_assert(my_is_same_v(std::declval())), int cvref >); \ + \ + static_assert(my_is_same_v(std::declval())), qreal cvref >); \ + static_assert(my_is_same_v(std::declval())), qreal cvref >); \ + static_assert(my_is_same_v(std::declval())), qreal cvref >); \ + static_assert(my_is_same_v(std::declval())), qreal cvref >) + +CHECK(&); +CHECK(const &); +CHECK(&&); +CHECK(const &&); + +#undef CHECK + #include #include diff --git a/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp b/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp index c183f79fb8c..76a4ccc0864 100644 --- a/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp +++ b/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp @@ -1,6 +1,28 @@ // Copyright (C) 2022 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +#include +#ifdef QVARIANT_H +# error "This test requires qpoint.h to not include qvariant.h" +#endif + +// don't assume +template +constexpr inline bool my_is_same_v = false; +template +constexpr inline bool my_is_same_v = true; + +#define CHECK(cvref) \ + static_assert(my_is_same_v(std::declval())), int cvref >); \ + static_assert(my_is_same_v(std::declval())), int cvref >) + +CHECK(&); +CHECK(const &); +CHECK(&&); +CHECK(const &&); + +#undef CHECK + #include #include diff --git a/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp b/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp index a6bd0a97791..14953039a1c 100644 --- a/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp +++ b/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp @@ -1,6 +1,28 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +#include +#ifdef QVARIANT_H +# error "This test requires qpoint.h to not include qvariant.h" +#endif + +// don't assume +template +constexpr inline bool my_is_same_v = false; +template +constexpr inline bool my_is_same_v = true; + +#define CHECK(cvref) \ + static_assert(my_is_same_v(std::declval())), qreal cvref >); \ + static_assert(my_is_same_v(std::declval())), qreal cvref >) + +CHECK(&); +CHECK(const &); +CHECK(&&); +CHECK(const &&); + +#undef CHECK + #include #include diff --git a/tests/auto/corelib/tools/qsize/tst_qsize.cpp b/tests/auto/corelib/tools/qsize/tst_qsize.cpp index 54ffd9fcfd4..77198c45764 100644 --- a/tests/auto/corelib/tools/qsize/tst_qsize.cpp +++ b/tests/auto/corelib/tools/qsize/tst_qsize.cpp @@ -1,6 +1,28 @@ // Copyright (C) 2022 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +#include +#ifdef QVARIANT_H +# error "This test requires qsize.h to not include qvariant.h" +#endif + +// don't assume +template +constexpr inline bool my_is_same_v = false; +template +constexpr inline bool my_is_same_v = true; + +#define CHECK(cvref) \ + static_assert(my_is_same_v(std::declval())), int cvref >); \ + static_assert(my_is_same_v(std::declval())), int cvref >) + +CHECK(&); +CHECK(const &); +CHECK(&&); +CHECK(const &&); + +#undef CHECK + #include #include diff --git a/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp b/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp index 0a53de68c9b..018f929ccae 100644 --- a/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp +++ b/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp @@ -1,6 +1,28 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +#include +#ifdef QVARIANT_H +# error "This test requires qsize.h to not include qvariant.h" +#endif + +// don't assume +template +constexpr inline bool my_is_same_v = false; +template +constexpr inline bool my_is_same_v = true; + +#define CHECK(cvref) \ + static_assert(my_is_same_v(std::declval())), qreal cvref >); \ + static_assert(my_is_same_v(std::declval())), qreal cvref >) + +CHECK(&); +CHECK(const &); +CHECK(&&); +CHECK(const &&); + +#undef CHECK + #include #include