1818
1919#include " invariant.h"
2020#include " expr.h"
21- #include " optional.h"
2221
2322// / \brief Check whether a reference to a generic \ref exprt is of a specific
2423// / derived class.
@@ -41,71 +40,70 @@ inline void validate_expr(const exprt &) {}
4140namespace detail // NOLINT
4241{
4342
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
4659
4760// / \brief Try to cast a reference to a generic exprt to a specific derived
4861// / class
4962// / \tparam T The reference or const reference type to \a TUnderlying to cast
5063// / to
5164// / \tparam TExpr The original type to cast from, either exprt or const exprt
5265// / \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
5568template <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
5871{
59- typedef typename std::decay<T>::type decayt;
72+ typedef
73+ typename detail::expr_try_dynamic_cast_return_typet<T, TExpr>::type
74+ returnt;
6075 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,
6277 " Tried to expr_try_dynamic_cast from something that wasn't an exprt" );
6378 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,
6880 " 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;
7486}
7587
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
8789{
88- return detail::expr_try_dynamic_cast<T>(base);
89- }
9090
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
10093{
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" );
10397
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+ };
106105
107- // We hide these functions in a namespace so that they only participate in
108- // overload resolution when explicitly requested.
106+ } // namespace detail
109107
110108// / \brief Cast a reference to a generic exprt to a specific derived class.
111109// / \tparam T The reference or const reference type to \a TUnderlying to cast to
@@ -114,23 +112,13 @@ namespace detail // NOLINT
114112// / \return Reference to object of type \a T
115113// / \throw std::bad_cast If \a base is not an instance of \a TUnderlying
116114template <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
118117{
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 )
130120 throw std::bad_cast ();
131- T ret=static_cast <T>(base);
132- validate_expr (ret);
133- return ret;
121+ return *ret;
134122}
135123
136124// / \brief Cast a reference to a generic exprt to a specific derived class.
@@ -143,69 +131,13 @@ T expr_dynamic_cast(TExpr &base)
143131// / \remark If CBMC assertions (PRECONDITION) are set to abort then this will
144132// / abort rather than throw if \a base is not an instance of \a TUnderlying
145133template <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
147136{
148- PRECONDITION (can_cast_expr<typename std::decay<T>::type >(base));
137+ PRECONDITION (can_cast_expr<T >(base));
149138 return expr_dynamic_cast<T>(base);
150139}
151140
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-
209141inline void validate_operands (
210142 const exprt &value,
211143 exprt::operandst::size_type number,
0 commit comments