spot 2.3.4

- Main Page
- Related Pages
- Modules
- Classes
- Files

- File List

All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
casts.hh
1 // -*- coding: utf-8 -*-
2 // Copyright (C) 2011, 2015-2017 Laboratoire de Recherche et Développement
3 // de l'Epita (LRDE).
4 //
5 // This file is part of Spot, a model checking library.
6 //
7 // Spot is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // Spot is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20 #pragma once
21
22 #include <memory>
23 #include <type_traits>
24
25 // We usually write code like
26 // subtypename* i = down_cast<subtypename*>(m);
27 // ... use i ...
28 // When NDEBUG is set, the down_cast is a fast static_cast.
29 // Otherwise, the down_cast is a dynamic_cast and may return 0
30 // on error, which is caught by an assert in the down_cast function.
31 //
32 // NB: It is valid to use down_cast with non-pointer template argument:
33 // subtypename& i = down_cast<subtypename&>(m);
34 // If an error occurs during the cast, an exception is thrown.
35 //
36 // NB: down_cast can also be used on shared_ptr.
37
38 namespace
39 {
40 // A helper struct to check that downcasts are performed down an inheritance
41 // hierarchy, not between unrelated types.
42 template<typename Base, typename Derived>
43 struct is_base_of : std::is_base_of<Base, Derived>
44 {};
45 template<typename Base, typename Derived>
46 struct is_base_of<Base*, Derived*> : is_base_of<Base, Derived>
47 {};
48 // Also handle smart pointers.
49 template<typename Base, typename Derived>
50 struct is_base_of<std::shared_ptr<Base>, std::shared_ptr<Derived>>
51 : is_base_of<Base, Derived>
52 {};
53
54 // std::is_pointer does not detect smart pointers.
55 // Make our own version that detects pointer, plain or smart.
56 template<typename T>
57 struct is_pointer : std::is_pointer<T>
58 {};
59 template<typename T>
60 struct is_pointer<std::shared_ptr<T>> : std::true_type
61 {};
62
63 template<typename T, typename U, bool check>
64 struct _downcast;
65
66 // A down-cast on non-pointer type is legitimate, e.g. down_cast<Derived&>(m);
67 // An error in the dynamic_cast will throw an exception.
68 template<typename T, typename U>
69 struct _downcast<T, U, false>
70 {
71 static_assert(is_base_of<U, T>::value, "invalid downcast");
72
73 static
74 inline
75 T
76 cast(U u)
77 #ifdef NDEBUG
78 noexcept
79 #else
80 noexcept(is_pointer<T>::value)
81 #endif
82 {
83 #ifdef NDEBUG
84 return static_cast<T>(u);
85 #else
86 return dynamic_cast<T>(u);
87 #endif
88 }
89 };
90
91 // A specialization for smart pointer, so that down_cast can be used
92 // uniformly.
93 // NB: Use
94 // auto d = down_cast<std::shared_ptr<T>>(b);
95 // instead of
96 // auto d = std::dynamic_pointer_cast<T>(b);
97 template<typename T, typename U>
98 struct _downcast<std::shared_ptr<T>, U, false>
99 {
100 static_assert(is_base_of<U, std::shared_ptr<T>>::value, "invalid downcast");
101
102 static
103 inline
104 std::shared_ptr<T>
105 cast(U u) noexcept
106 {
107 #ifdef NDEBUG
108 return std::static_pointer_cast<T>(u);
109 #else
110 return std::dynamic_pointer_cast<T>(u);
111 #endif
112 }
113 };
114
115 // Pointer type specialization.
116 // Cast errors are caught by an assertion, no exception is thrown.
117 template<typename T, typename U>
118 struct _downcast<T, U, true>
119 {
120 static
121 inline
122 T
123 cast(U u) noexcept
124 {
125 T t = _downcast<T, U, false>::cast(u);
126 SPOT_ASSERT(t);
127 return t;
128 }
129 };
130 } // anonymous namespace
131
132 // The actual function to call.
133 template<typename T, typename U>
134 inline
135 T
136 down_cast(U u)
137 #ifdef NDEBUG
138 noexcept
139 #else
140 noexcept(is_pointer<T>::value)
141 #endif
142 {
143 return _downcast<T, U, is_pointer<T>::value>::cast(u);
144 }
145
std
Definition: formula.hh:1671
spot::op::U
until

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.