// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz // Copyright (C) 2022 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include #include #include #include #include struct Private : QSharedData {}; class tst_q20_memory : public QObject { Q_OBJECT private Q_SLOTS: void raw(); void smart(); void recursion(); void usesPointerTraits(); void prefersPointerTraits(); private Q_SLOTS: void to_address_broken_const_propagation_QExplicitlySharedDataPointer() { to_address_broken_const_propagation>(); } void to_address_broken_const_propagation_QSharedDataPointer() { to_address_broken_const_propagation>(); } void to_address_broken_const_propagation_shared_ptr() { to_address_broken_const_propagation>(); } void to_address_broken_const_propagation_unique_ptr() { to_address_broken_const_propagation>(); } private: template void to_address_broken_const_propagation(); }; void tst_q20_memory::raw() { auto i = 0; auto p = &i; QVERIFY(q20::to_address(p) == &i); } template class MinimalPtr { public: using element_type = T; explicit MinimalPtr(T *d) : d(d) {} T *operator->() const noexcept { return d; } private: T *d; }; void tst_q20_memory::smart() { int i; MinimalPtr ptr(&i); QCOMPARE_EQ(q20::to_address(ptr), &i); } template class RecursivePtr { public: using element_type = T; explicit RecursivePtr(T *d) : d(d) {} MinimalPtr operator->() const noexcept { return d; } private: MinimalPtr d; }; void tst_q20_memory::recursion() { int i; RecursivePtr ptr(&i); QCOMPARE_EQ(q20::to_address(ptr), &i); } template class NoDerefOperatorPtr { public: using element_type = T; explicit NoDerefOperatorPtr(T *d) : d(d) {} T *get() const noexcept { return d; } private: T *d; }; namespace std { template struct pointer_traits> { static T *to_address(const NoDerefOperatorPtr &ptr) noexcept { return ptr.get(); } }; } // namespace std void tst_q20_memory::usesPointerTraits() { int i; NoDerefOperatorPtr ptr(&i); QCOMPARE_EQ(q20::to_address(ptr), &i); } template class PrefersPointerTraitsPtr { public: using element_type = T; explicit PrefersPointerTraitsPtr(T *d) : d(d) {} T *operator->() const noexcept { return nullptr; } T *get() const noexcept { return d; } private: T *d; }; namespace std { template struct pointer_traits> { static T *to_address(const PrefersPointerTraitsPtr &p) noexcept { return p.get(); } }; } // namespace std void tst_q20_memory::prefersPointerTraits() { int i; PrefersPointerTraitsPtr ptr(&i); QCOMPARE_EQ(q20::to_address(ptr), &i); } template void tst_q20_memory::to_address_broken_const_propagation() { Pointer p(nullptr); QCOMPARE_EQ(q20::to_address(p), nullptr); p = Pointer{new Private()}; QCOMPARE_EQ(q20::to_address(p), p.operator->()); static_assert(std::is_same_v())>); } QTEST_GUILESS_MAIN(tst_q20_memory) #include "tst_q20_memory.moc"