-
Notifications
You must be signed in to change notification settings - Fork 280
Add try_dynamic_cast from rvalue to optionalt
#4028
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add try_dynamic_cast from rvalue to optionalt
#4028
Conversation
src/util/expr_cast.h
Outdated
@@ -107,6 +107,32 @@ auto expr_try_dynamic_cast(TExpr &base) | |||
return ret; | |||
} | |||
|
|||
/// \brief Try to cast a generic exprt to a specific derived class. | |||
/// \tparam T: The type to cast the `base` param to. | |||
/// \tparam TType: The original type to cast from, Must be a exprt rvalue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit pick: s/Must/must/
src/util/expr_cast.h
Outdated
@@ -107,6 +107,32 @@ auto expr_try_dynamic_cast(TExpr &base) | |||
return ret; | |||
} | |||
|
|||
/// \brief Try to cast a generic exprt to a specific derived class. | |||
/// \tparam T: The type to cast the `base` param to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit pick: I'd use \p base
(it will be rendered the same way, but conveys the fact that this is a parameter)
return {}; | ||
optionalt<T> ret{static_cast<T &&>(base)}; | ||
validate_expr(*ret); | ||
return ret; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It probably doesn't make much of a difference, other than saving one line, but I'd have used:
validate_expr(base);
return std::move(base);
src/util/expr_cast.h
Outdated
@@ -134,6 +160,31 @@ auto type_try_dynamic_cast(TType &base) -> | |||
return ret; | |||
} | |||
|
|||
/// \brief Try to cast a generic typet to a specific derived class. | |||
/// \tparam T: The type to cast the `base` param to. | |||
/// \tparam TType: The original type to cast from, Must be a typet rvalue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the same comments as above apply...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, one nitpick
unit/util/expr_cast/expr_cast.cpp
Outdated
{ | ||
typet type = string_type; | ||
|
||
THEN("Trying casting a value to a string_typet should yield a non null " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a value
-> a string type
throughout?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. I think the update should be a value
-> a typet lvalue
, in order to make things clear.
This commit adds templates for `expr_try_dynamic_cast` and `type_try_dynamic_cast` where the parameter is an rvalue and the return type is an `optionalt`. This is implemented by moving the parameter into the `optionalt`. Included are unit tests of the new templates, which show that they return the types and values expected. As well as tests and a static assert for the existing overloads which show that they still return a pointer. These new templates are useful in the case where we are using the result of a function, which returns by value but only in the case where the value can be cast to a given type. For example with the new overloads the following code can be written - ``` exprt enig(); void handle_struct_case(const struct_exprt &struct_expr); void myFunction() { if(const auto my_struct = expr_try_dynamic_cast<struct_exprt>(enig())) handle_struct_case(*my_struct); } ``` However without the new templates and because the old ones do not bind to rvalues, an additional temporary variable otherwise would have to be declared - ``` void myFunction2() { const exprt enigma = enig(); if(const auto my_struct = expr_try_dynamic_cast<struct_exprt>(enigma)) handle_struct_case(*my_struct); } ```
6fd8653
to
52e95a6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
Passed Diffblue compatibility checks (cbmc commit: 52e95a6).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/99777773
This pr adds templates for
expr_try_dynamic_cast
andtype_try_dynamic_cast
where the parameter is an rvalue and the returntype is an
optionalt
. This is implemented by moving the parameter intothe
optionalt
.Included are unit tests of the new templates, which show that they
return the types and values expected. As well as tests and a static
assert for the existing overloads which show that they still return a
pointer.
These new templates are useful in the case where we are using the
result of a function, which returns by value but only in the case where
the value can be cast to a given type. For example with the new
overloads the following code can be written -
However without the new templates and because the old ones do not bind
to rvalues, an additional temporary variable otherwise would have to be
declared -