Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
cast.h
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
5#ifndef INKSCAPE_UTIL_CAST_H
6#define INKSCAPE_UTIL_CAST_H
7
8#include <type_traits>
9
10/*
11 * In order to use this system with a class hierarchy, specialize the following templates for
12 * every member of the hierarchy. The only requirement is that
13 *
14 * first_tag<T> <= first_tag<S> <= last_tag<T>
15 *
16 * exactly when S is a derived class of T. Then add to each class the line of boilerplate
17 *
18 * int tag() const override { return tag_of<decltype(*this)>; }
19 */
20template <typename T> inline constexpr int first_tag = std::enable_if<!sizeof(T), void>::value;
21template <typename T> inline constexpr int last_tag = std::enable_if<!sizeof(T), void>::value;
22
26template <typename T> inline constexpr int tag_of = first_tag<std::remove_cv_t<std::remove_reference_t<T>>>;
27
36template<typename T, typename S>
37bool is(S const *s)
38{
39 if (!s) return false;
40 if constexpr (std::is_base_of_v<T, S>) {
41 static_assert(!sizeof(T), "check is always true");
42 return true;
43 } else if constexpr (std::is_base_of_v<S, T>) {
44 auto const s_tag = s->tag();
45 return first_tag<T> <= s_tag && s_tag <= last_tag<T>;
46 } else {
47 static_assert(!sizeof(T), "check is always false");
48 return false;
49 }
50}
51
55template<typename T, typename S>
56auto cast_unsafe(S *s)
57{
58 return static_cast<T*>(s);
59}
60
61template<typename T, typename S>
62auto cast_unsafe(S const *s)
63{
64 return static_cast<T const*>(s);
65}
66
75template<typename T, typename S>
76auto cast(S *s)
77{
78 if constexpr (std::is_base_of_v<T, S>) {
79 // Removed static assert; it complicates template "collect_items"
80 // static_assert(!sizeof(T), "cast is unnecessary");
81 return cast_unsafe<T>(s);
82 } else if constexpr (std::is_base_of_v<S, T>) {
83 return is<T>(s) ? cast_unsafe<T>(s) : nullptr;
84 } else {
85 static_assert(!sizeof(T), "cast is impossible");
86 return nullptr;
87 }
88}
89
90#endif // INKSCAPE_UTIL_CAST_H
91
92/*
93 Local Variables:
94 mode:c++
95 c-file-style:"stroustrup"
96 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
97 indent-tabs-mode:nil
98 fill-column:99
99 End:
100*/
101// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
auto cast(S *s)
Equivalent to dynamic_cast<T [const]*>(...) where the const is deduced.
Definition cast.h:76
bool is(S const *s)
Equivalent to the boolean value of dynamic_cast<T const*>(...).
Definition cast.h:37
constexpr int last_tag
Definition cast.h:21
auto cast_unsafe(S *s)
Equivalent to static_cast<T [const]*>(...) where the const is deduced.
Definition cast.h:56
constexpr int first_tag
Definition cast.h:20
constexpr int tag_of
Convenience function to retrieve the tag (class id) of a given type.
Definition cast.h:26