base: Strengthen safe_cast and make it work for reference types
safe_cast now supports the exact same types as dynamic_cast would. In particular, it now supports l-value references and rejects r-value references. The non-debug version has also been updated to make it build only in the same cases as the debug version of safe_cast would. Change-Id: I86692561c169b1ad063000c990a52ea80c6637ca Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67453 Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Gabriel B.
parent
1b949e9759
commit
3bdbe482c2
@@ -30,6 +30,8 @@
|
||||
#define __BASE_CAST_HH__
|
||||
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
#include "base/logging.hh"
|
||||
|
||||
namespace gem5
|
||||
{
|
||||
@@ -44,10 +46,20 @@ namespace gem5
|
||||
|
||||
template <class T, class U>
|
||||
inline T
|
||||
safe_cast(U ptr)
|
||||
safe_cast(U&& ref_or_ptr)
|
||||
{
|
||||
T ret = dynamic_cast<T>(ptr);
|
||||
assert(ret);
|
||||
/*
|
||||
* srd::forward used in conjunction with forwarding references (template T
|
||||
* + T&&) ensures that dynamic_cast will see the exact same type that was
|
||||
* passed to safe_cast (a.k.a., perfect forwarding).
|
||||
*
|
||||
* Not using std::forward would make safe_cast compile with references to
|
||||
* temporary objects and thus return a dangling reference.
|
||||
*/
|
||||
T ret = dynamic_cast<T>(std::forward<U>(ref_or_ptr));
|
||||
if constexpr (std::is_pointer_v<T>) {
|
||||
gem5_assert(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -59,9 +71,19 @@ safe_cast(U ptr)
|
||||
|
||||
template <class T, class U>
|
||||
inline T
|
||||
safe_cast(U ptr)
|
||||
safe_cast(U&& ref_or_ptr)
|
||||
{
|
||||
return static_cast<T>(ptr);
|
||||
/*
|
||||
* safe_cast should be reserved to polymorphic types while static_cast is
|
||||
* also allowed for non-polymorphic types. It could make safe_cast able to
|
||||
* compile in a non-debug build and fail in a debug build.
|
||||
*/
|
||||
static_assert(std::is_polymorphic_v<
|
||||
std::remove_pointer_t<
|
||||
std::remove_reference_t<
|
||||
U>>
|
||||
>);
|
||||
return static_cast<T>(std::forward<U>(ref_or_ptr));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user