Skip to content

Commit 7033168

Browse files
committed
Short live pointer_cast!
A collection of helper functions to ease porting from `QSharedPointer` to `std::shared_ptr`, by helping with the most egregious API incompatibilites of QSharedPointer, to wit: - static_pointer_cast overload for QSharedPointer - dynamic_pointer_cast overload for QSharedPointer - const_pointer_cast overload for QSharedPointer - make_qshared - like std::make_shared, but returning QSharedPointer The casts are designed to be used like their `std` counterparts operating on `std::shared_ptr`. We advise to used unqualified lookup QSharedPointer<Base> base = make_qshared<Derived>(~~~); auto derived = dynamic_pointer_cast<Derived>(base); // not KDToolBox::... If you target C++20, then this is also the way to call `std::dynamic_pointer_cast` (unqualifed lookup of functions with explicit template arguments doesn't find candidates by ADL prior to C++20) For this reason, the functions are defined in `inline namespace KDToolBox`. If you restict your code to the std-compatible subset of QSharedPointer and use te above four functions, then porting from QSharedPointer to std::shared_ptr will be as easy as s/QSharedPointer/std::shared_ptr/ s/QWeakPointer/std::weak_ptr/ s/make_qshared/std::make_shared/ Enjoy! Change-Id: I4265c8568e61196d5494f98798515f101e8d4e67 Reviewed-on: https://codereview.kdab.com/c/kdab/KDToolBox/+/97789 Tested-by: Continuous Integration <[email protected]> Reviewed-by: Milian Wolff <[email protected]> Reviewed-by: Giuseppe D'Angelo <[email protected]>
1 parent 590f76e commit 7033168

File tree

7 files changed

+209
-0
lines changed

7 files changed

+209
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ Qt Tools
5858
Intercept `Q_ASSERT` failures with ASAN and print a backtrace.
5959
- [KDSqlDatabaseTransaction](https://github.com/KDAB/KDToolBox/tree/master/qt/KDSqlDatabaseTransaction)
6060
A RAII wrapper for database transactions when using the Qt SQL APIs.
61+
- [pointer_cast](https://github.com/KDAB/KDToolBox/tree/master/qt/pointer_cast)
62+
Tools to ease migrating from `QSharedPointer` to `std::shared_ptr`.
6163

6264
Other code snippets
6365
===================

qt/pointer_cast/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
pointer-cast
2+
==================
3+
4+
A collection of helper functions to ease porting from `QSharedPointer`
5+
to `std::shared_ptr`, by helping with the most egregious API
6+
incompatibilites of QSharedPointer, to wit:
7+
8+
- static_pointer_cast overload for QSharedPointer
9+
- dynamic_pointer_cast overload for QSharedPointer
10+
- const_pointer_cast overload for QSharedPointer
11+
- make_qshared - like std::make_shared, but returning QSharedPointer
12+
13+
The casts are designed to be used like their `std` counterparts
14+
operating on `std::shared_ptr`. We advise to used unqualified lookup
15+
16+
QSharedPointer<Base> base = make_qshared<Derived>(~~~);
17+
auto derived = dynamic_pointer_cast<Derived>(base); // not KDToolBox::...
18+
19+
If you target C++20, then this is also the way to call
20+
`std::dynamic_pointer_cast` (unqualifed lookup of functions with
21+
explicit template arguments doesn't find candidates by ADL prior to
22+
C++20) For this reason, the functions are defined in `inline namespace
23+
KDToolBox`.
24+
25+
If you restict your code to the std-compatible subset of
26+
QSharedPointer and use te above four functions, then porting from
27+
QSharedPointer to std::shared_ptr will be as easy as
28+
29+
s/QSharedPointer/std::shared_ptr/
30+
s/QWeakPointer/std::weak_ptr/
31+
s/make_qshared/std::make_shared/
32+
33+
Enjoy!

qt/pointer_cast/pointer_cast.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/****************************************************************************
2+
** MIT License
3+
**
4+
** Copyright (C) 2020-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, [email protected]
5+
** Author: Giuseppe D'Angelo <[email protected]>
6+
**
7+
** This file is part of KDToolBox (https://github.com/KDAB/KDToolBox).
8+
**
9+
** Permission is hereby granted, free of charge, to any person obtaining a copy
10+
** of this software and associated documentation files (the "Software"), to deal
11+
** in the Software without restriction, including without limitation the rights
12+
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
** copies of the Software, ** and to permit persons to whom the Software is
14+
** furnished to do so, subject to the following conditions:
15+
**
16+
** The above copyright notice and this permission notice (including the next paragraph)
17+
** shall be included in all copies or substantial portions of the Software.
18+
**
19+
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
** LIABILITY, WHETHER IN AN ACTION OF ** CONTRACT, TORT OR OTHERWISE,
24+
** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25+
** DEALINGS IN THE SOFTWARE.
26+
****************************************************************************/
27+
28+
#pragma once
29+
30+
#include <QSharedPointer>
31+
32+
#include <utility>
33+
34+
inline namespace KDToolBox {
35+
36+
template <typename To, typename From>
37+
QSharedPointer<To> static_pointer_cast(const QSharedPointer<From>& from)
38+
{
39+
return from.template staticCast<To>();
40+
}
41+
42+
template <typename To, typename From>
43+
QSharedPointer<To> dynamic_pointer_cast(const QSharedPointer<From>& from)
44+
{
45+
return from.template dynamicCast<To>();
46+
}
47+
48+
template <typename To, typename From>
49+
QSharedPointer<To> const_pointer_cast(const QSharedPointer<From>& from)
50+
{
51+
return from.template constCast<To>();
52+
}
53+
54+
template <typename T, typename...Args>
55+
QSharedPointer<T> make_qshared(Args&&...args)
56+
{
57+
return QSharedPointer<T>::create(std::forward<Args>(args)...);
58+
}
59+
60+
} // namespace KDToolBox

qt/pointer_cast/pointer_cast.pro

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
TEMPLATE = subdirs
2+
3+
HEADERS += \
4+
pointer_cast.h \
5+
6+
SUBDIRS += \
7+
test \

qt/pointer_cast/test/test.pro

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
TEMPLATE = app
2+
TARGET = tst_pointer_cast
3+
QT = core testlib
4+
CONFIG += testcase c++14
5+
6+
SOURCES += \
7+
tst_pointer_cast.cpp \
8+
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/****************************************************************************
2+
** MIT License
3+
**
4+
** Copyright (C) 2019-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, [email protected]
5+
**
6+
** This file is part of KDToolBox (https://github.com/KDAB/KDToolBox).
7+
**
8+
** Permission is hereby granted, free of charge, to any person obtaining a copy
9+
** of this software and associated documentation files (the "Software"), to deal
10+
** in the Software without restriction, including without limitation the rights
11+
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
** copies of the Software, ** and to permit persons to whom the Software is
13+
** furnished to do so, subject to the following conditions:
14+
**
15+
** The above copyright notice and this permission notice (including the next paragraph)
16+
** shall be included in all copies or substantial portions of the Software.
17+
**
18+
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
** LIABILITY, WHETHER IN AN ACTION OF ** CONTRACT, TORT OR OTHERWISE,
23+
** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24+
** DEALINGS IN THE SOFTWARE.
25+
****************************************************************************/
26+
27+
#include <QTest>
28+
29+
#include "../pointer_cast.h"
30+
31+
class tst_pointer_cast : public QObject
32+
{
33+
Q_OBJECT
34+
35+
private Q_SLOTS:
36+
void makeQShared();
37+
void staticCast();
38+
void dynamicCast();
39+
void constCast();
40+
};
41+
42+
namespace {
43+
44+
struct B {
45+
virtual ~B() = default;
46+
};
47+
48+
struct D : B {};
49+
50+
struct D2 : B {};
51+
52+
} // unnamed namespace
53+
54+
void tst_pointer_cast::makeQShared()
55+
{
56+
{
57+
auto p = make_qshared<int>(42);
58+
Q_STATIC_ASSERT((std::is_same<decltype(p), QSharedPointer<int>>::value));
59+
QVERIFY(p);
60+
QCOMPARE(*p, 42);
61+
}
62+
{
63+
auto p = make_qshared<QString>("Hello");
64+
Q_STATIC_ASSERT((std::is_same<decltype(p), QSharedPointer<QString>>::value));
65+
QVERIFY(p);
66+
QCOMPARE(*p, "Hello");
67+
}
68+
}
69+
70+
void tst_pointer_cast::staticCast()
71+
{
72+
auto b = make_qshared<D>();
73+
QVERIFY(b);
74+
auto d = static_pointer_cast<D>(b);
75+
QCOMPARE(b, d);
76+
}
77+
78+
void tst_pointer_cast::dynamicCast()
79+
{
80+
auto b = make_qshared<D>();
81+
QVERIFY(b);
82+
auto d = dynamic_pointer_cast<D>(b);
83+
QCOMPARE(b, d);
84+
auto d2 = dynamic_pointer_cast<D2>(b);
85+
QCOMPARE(d2, nullptr);
86+
}
87+
88+
void tst_pointer_cast::constCast()
89+
{
90+
auto cd = make_qshared<const D>();
91+
QVERIFY(cd);
92+
auto md = const_pointer_cast<D>(cd);
93+
QCOMPARE(md, cd);
94+
}
95+
96+
QTEST_MAIN(tst_pointer_cast)
97+
98+
#include "tst_pointer_cast.moc"

qt/qt.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ SUBDIRS += \
66
messagehandler \
77
model_view \
88
notify_guard \
9+
pointer_cast \
910
qml \
1011
qt_hasher \
1112
singleshot_connect \

0 commit comments

Comments
 (0)