forked from RobotLocomotion/drake
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pointer_cast.h
76 lines (68 loc) · 2.79 KB
/
pointer_cast.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#pragma once
#include <memory>
#include <stdexcept>
#include <fmt/format.h>
#include "drake/common/nice_type_name.h"
namespace drake {
/// Casts the object owned by the std::unique_ptr `other` from type `U` to `T`;
/// no runtime type checking is performed.
///
/// This method is analogous to the built-in std::static_pointer_cast that
/// operates on a std::shared_ptr.
///
/// Note that this function only supports default deleters.
template <class T, class U>
std::unique_ptr<T> static_pointer_cast(std::unique_ptr<U>&& other) noexcept {
return std::unique_ptr<T>(static_cast<T*>(other.release()));
}
/// Casts the object owned by the std::unique_ptr `other` from type `U` to `T`;
/// if the cast fails, returns nullptr. Casting is performed using
/// `dynamic_cast` on the managed value (i.e., the result of `other.get()`).
/// On success, `other`'s managed value is transferred to the result and
/// `other` is empty; on failure, `other` will retain its original managed
/// value and the result is empty. As with `dynamic_cast`, casting nullptr to
/// anything always succeeds, so a nullptr result could indicate either that
/// the argument was nullptr or that the cast failed.
///
/// This method is analogous to the built-in std::dynamic_pointer_cast that
/// operates on a std::shared_ptr.
///
/// Note that this function only supports default deleters.
template <class T, class U>
std::unique_ptr<T> dynamic_pointer_cast(std::unique_ptr<U>&& other) noexcept {
T* result = dynamic_cast<T*>(other.get());
if (!result) { return nullptr; }
other.release();
return std::unique_ptr<T>(result);
}
/// Casts the object owned by the std::unique_ptr `other` from type `U` to `T`;
/// if `other` is nullptr or the cast fails, throws a std::logic_error.
/// Casting is performed using `dynamic_cast` on the managed value (i.e., the
/// result of `other.get()`). On success, `other`'s managed value is
/// transferred to the result and `other` is empty; on failure, `other` will
/// retain its original managed value.
///
/// @throws std::logic_error if the cast fails.
///
/// Note that this function only supports default deleters.
template <class T, class U>
std::unique_ptr<T> dynamic_pointer_cast_or_throw(std::unique_ptr<U>&& other) {
if (!other) {
throw std::logic_error(fmt::format(
"Cannot cast a unique_ptr<{}> containing nullptr to unique_ptr<{}>.",
NiceTypeName::Get<U>(),
NiceTypeName::Get<T>()));
}
T* result = dynamic_cast<T*>(other.get());
if (!result) {
throw std::logic_error(fmt::format(
"Cannot cast a unique_ptr<{}> containing an object of type {} to "
"unique_ptr<{}>.",
NiceTypeName::Get<U>(),
NiceTypeName::Get(*other),
NiceTypeName::Get<T>()));
}
other.release();
return std::unique_ptr<T>(result);
}
} // namespace drake