@@ -18,7 +18,6 @@ Author: Nathan Phillips <Nathan.Phillips@diffblue.com>
18
18
19
19
#include " invariant.h"
20
20
#include " expr.h"
21
- #include " optional.h"
22
21
23
22
// / \brief Check whether a reference to a generic \ref exprt is of a specific
24
23
// / derived class.
@@ -41,71 +40,70 @@ inline void validate_expr(const exprt &) {}
41
40
namespace detail // NOLINT
42
41
{
43
42
44
- // We hide these functions in a namespace so that they only participate in
45
- // overload resolution when explicitly requested.
43
+ template <typename Ret, typename T>
44
+ struct expr_try_dynamic_cast_return_typet final
45
+ {
46
+ static_assert (
47
+ !std::is_reference<Ret>::value,
48
+ " Ret must be non-qualified" );
49
+
50
+ typedef
51
+ typename std::conditional<
52
+ std::is_const<T>::value,
53
+ typename std::add_const<Ret>::type,
54
+ Ret>::type *
55
+ type;
56
+ };
57
+
58
+ } // namespace detail
46
59
47
60
// / \brief Try to cast a reference to a generic exprt to a specific derived
48
61
// / class
49
62
// / \tparam T The reference or const reference type to \a TUnderlying to cast
50
63
// / to
51
64
// / \tparam TExpr The original type to cast from, either exprt or const exprt
52
65
// / \param base Reference to a generic \ref exprt
53
- // / \return Reference to object of type \a TUnderlying
54
- // / or valueless optional if \a base is not an instance of \a TUnderlying
66
+ // / \return Ptr to object of type \a TUnderlying
67
+ // / or nullptr if \a base is not an instance of \a TUnderlying
55
68
template <typename T, typename TExpr>
56
- optionalt<std::reference_wrapper< typename std::remove_reference<T>::type>>
57
- expr_try_dynamic_cast (TExpr &base)
69
+ auto expr_try_dynamic_cast (TExpr &base)
70
+ -> typename detail::expr_try_dynamic_cast_return_typet<T, TExpr>::type
58
71
{
59
- typedef typename std::decay<T>::type decayt;
72
+ typedef
73
+ typename detail::expr_try_dynamic_cast_return_typet<T, TExpr>::type
74
+ returnt;
60
75
static_assert (
61
- std::is_same<typename std::remove_const <TExpr>::type, exprt>::value,
76
+ std::is_same<typename std::decay <TExpr>::type, exprt>::value,
62
77
" Tried to expr_try_dynamic_cast from something that wasn't an exprt" );
63
78
static_assert (
64
- std::is_reference<T>::value,
65
- " Tried to convert exprt & to non-reference type" );
66
- static_assert (
67
- std::is_base_of<exprt, decayt>::value,
79
+ std::is_base_of<exprt, T>::value,
68
80
" The template argument T must be derived from exprt." );
69
- if (!can_cast_expr<decayt >(base))
70
- return {} ;
71
- T ret=static_cast <T>( base);
72
- validate_expr (ret);
73
- return std::reference_wrapper< typename std::remove_reference<T>::type>( ret) ;
81
+ if (!can_cast_expr<T >(base))
82
+ return nullptr ;
83
+ const auto ret=static_cast <returnt>(& base);
84
+ validate_expr (* ret);
85
+ return ret;
74
86
}
75
87
76
- } // namespace detail
77
-
78
- // / \brief Try to cast a constant reference to a generic exprt to a specific
79
- // / derived class
80
- // / \tparam T The exprt-derived class to cast to
81
- // / \param base Reference to a generic \ref exprt
82
- // / \return Reference to object of type \a T or valueless optional if \a base
83
- // / is not an instance of \a T
84
- template <typename T>
85
- optionalt<std::reference_wrapper<typename std::remove_reference<T>::type>>
86
- expr_try_dynamic_cast (const exprt &base)
88
+ namespace detail // NOLINT
87
89
{
88
- return detail::expr_try_dynamic_cast<T>(base);
89
- }
90
90
91
- // / \brief Try to cast a reference to a generic exprt to a specific derived
92
- // / class
93
- // / \tparam T The exprt-derived class to cast to
94
- // / \param base Reference to a generic \ref exprt
95
- // / \return Reference to object of type \a T or valueless optional if \a base is
96
- // / not an instance of \a T
97
- template <typename T>
98
- optionalt<std::reference_wrapper<typename std::remove_reference<T>::type>>
99
- expr_try_dynamic_cast (exprt &base)
91
+ template <typename Ret, typename T>
92
+ struct expr_dynamic_cast_return_typet final
100
93
{
101
- return detail::expr_try_dynamic_cast<T>(base);
102
- }
94
+ static_assert (
95
+ !std::is_reference<Ret>::value,
96
+ " Ret must be non-qualified" );
103
97
104
- namespace detail // NOLINT
105
- {
98
+ typedef
99
+ typename std::conditional<
100
+ std::is_const<T>::value,
101
+ typename std::add_const<Ret>::type,
102
+ Ret>::type &
103
+ type;
104
+ };
106
105
107
- // We hide these functions in a namespace so that they only participate in
108
- // overload resolution when explicitly requested.
106
+ } // namespace detail
109
107
110
108
// / \brief Cast a reference to a generic exprt to a specific derived class.
111
109
// / \tparam T The reference or const reference type to \a TUnderlying to cast to
@@ -114,23 +112,13 @@ namespace detail // NOLINT
114
112
// / \return Reference to object of type \a T
115
113
// / \throw std::bad_cast If \a base is not an instance of \a TUnderlying
116
114
template <typename T, typename TExpr>
117
- T expr_dynamic_cast (TExpr &base)
115
+ auto expr_dynamic_cast (TExpr &base)
116
+ -> typename detail::expr_dynamic_cast_return_typet<T, TExpr>::type
118
117
{
119
- typedef typename std::decay<T>::type decayt;
120
- static_assert (
121
- std::is_same<typename std::remove_const<TExpr>::type, exprt>::value,
122
- " Tried to expr_dynamic_cast from something that wasn't an exprt" );
123
- static_assert (
124
- std::is_reference<T>::value,
125
- " Tried to convert exprt & to non-reference type" );
126
- static_assert (
127
- std::is_base_of<exprt, decayt>::value,
128
- " The template argument T must be derived from exprt." );
129
- if (!can_cast_expr<decayt>(base))
118
+ const auto ret=expr_try_dynamic_cast<T>(base);
119
+ if (ret==nullptr )
130
120
throw std::bad_cast ();
131
- T ret=static_cast <T>(base);
132
- validate_expr (ret);
133
- return ret;
121
+ return *ret;
134
122
}
135
123
136
124
// / \brief Cast a reference to a generic exprt to a specific derived class.
@@ -143,69 +131,13 @@ T expr_dynamic_cast(TExpr &base)
143
131
// / \remark If CBMC assertions (PRECONDITION) are set to abort then this will
144
132
// / abort rather than throw if \a base is not an instance of \a TUnderlying
145
133
template <typename T, typename TExpr>
146
- T expr_checked_cast (TExpr &base)
134
+ auto expr_checked_cast (TExpr &base)
135
+ -> typename detail::expr_dynamic_cast_return_typet<T, TExpr>::type
147
136
{
148
- PRECONDITION (can_cast_expr<typename std::decay<T>::type >(base));
137
+ PRECONDITION (can_cast_expr<T >(base));
149
138
return expr_dynamic_cast<T>(base);
150
139
}
151
140
152
- } // namespace detail
153
-
154
- // / \brief Cast a constant reference to a generic exprt to a specific derived
155
- // / class
156
- // / \tparam T The exprt-derived class to cast to
157
- // / \param base Reference to a generic \ref exprt
158
- // / \return Reference to object of type \a T
159
- // / \throw std::bad_cast If \a base is not an instance of \a T
160
- // / \remark If CBMC assertions (PRECONDITION) are set to abort then this will
161
- // / abort rather than throw if \a base is not an instance of \a T
162
- template <typename T>
163
- T expr_dynamic_cast (const exprt &base)
164
- {
165
- return detail::expr_dynamic_cast<T>(base);
166
- }
167
-
168
- // / \brief Cast a reference to a generic exprt to a specific derived class
169
- // / \tparam T The exprt-derived class to cast to
170
- // / \param base Reference to a generic \ref exprt
171
- // / \return Reference to object of type \a T
172
- // / \throw std::bad_cast If \a base is not an instance of \a T
173
- // / \remark If CBMC assertions (PRECONDITION) are set to abort then this will
174
- // / abort rather than throw if \a base is not an instance of \a T
175
- template <typename T>
176
- T expr_dynamic_cast (exprt &base)
177
- {
178
- return detail::expr_dynamic_cast<T>(base);
179
- }
180
-
181
- // / \brief Cast a constant reference to a generic exprt to a specific derived
182
- // / class. Also assert that the exprt invariants are not violated.
183
- // / \tparam T The exprt-derived class to cast to
184
- // / \param base Reference to a generic \ref exprt
185
- // / \return Reference to object of type \a T
186
- // / \throw std::bad_cast If \a base is not an instance of \a T
187
- // / \remark If CBMC assertions (PRECONDITION) are set to abort then this will
188
- // / abort rather than throw if \a base is not an instance of \a T
189
- template <typename T>
190
- T expr_checked_cast (const exprt &base)
191
- {
192
- return detail::expr_checked_cast<T>(base);
193
- }
194
-
195
- // / \brief Cast a reference to a generic exprt to a specific derived class.
196
- // / Also assert that the exprt invariants are not violated.
197
- // / \tparam T The exprt-derived class to cast to
198
- // / \param base Reference to a generic \ref exprt
199
- // / \return Reference to object of type \a T
200
- // / \throw std::bad_cast If \a base is not an instance of \a T
201
- // / \remark If CBMC assertions (PRECONDITION) are set to abort then this will
202
- // / abort rather than throw if \a base is not an instance of \a T
203
- template <typename T>
204
- T expr_checked_cast (exprt &base)
205
- {
206
- return detail::expr_checked_cast<T>(base);
207
- }
208
-
209
141
inline void validate_operands (
210
142
const exprt &value,
211
143
exprt::operandst::size_type number,
0 commit comments