util/IntrusiveList: add type alias "Hook"
By casting to SafeLinkIntrusiveListHook if appropriate, this fixes a bug in the erase() method, where erase() calls IntrusiveListHook::unlink() instead of SafeLinkIntrusiveListHook::unlink().
This commit is contained in:
@@ -99,28 +99,42 @@ public:
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class IntrusiveList {
|
class IntrusiveList {
|
||||||
|
/**
|
||||||
|
* Detect the hook type; this is important because
|
||||||
|
* SafeLinkIntrusiveListHook::unlink() needs to clear the
|
||||||
|
* "next" pointer. This is a template to postpone the type
|
||||||
|
* checks, to allow forward-declared types.
|
||||||
|
*/
|
||||||
|
template<typename U>
|
||||||
|
struct HookDetection {
|
||||||
|
static_assert(std::is_base_of_v<IntrusiveListHook, U>);
|
||||||
|
|
||||||
|
using type = std::conditional_t<std::is_base_of_v<SafeLinkIntrusiveListHook, U>,
|
||||||
|
SafeLinkIntrusiveListHook,
|
||||||
|
IntrusiveListHook>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
using Hook = typename HookDetection<U>::type;
|
||||||
|
|
||||||
IntrusiveListNode head{&head, &head};
|
IntrusiveListNode head{&head, &head};
|
||||||
|
|
||||||
static constexpr T *Cast(IntrusiveListNode *node) noexcept {
|
static constexpr T *Cast(IntrusiveListNode *node) noexcept {
|
||||||
static_assert(std::is_base_of<IntrusiveListHook, T>::value);
|
auto *hook = &Hook<T>::Cast(*node);
|
||||||
auto *hook = &IntrusiveListHook::Cast(*node);
|
|
||||||
return static_cast<T *>(hook);
|
return static_cast<T *>(hook);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr const T *Cast(const IntrusiveListNode *node) noexcept {
|
static constexpr const T *Cast(const IntrusiveListNode *node) noexcept {
|
||||||
static_assert(std::is_base_of<IntrusiveListHook, T>::value);
|
const auto *hook = &Hook<T>::Cast(*node);
|
||||||
const auto *hook = &IntrusiveListHook::Cast(*node);
|
|
||||||
return static_cast<const T *>(hook);
|
return static_cast<const T *>(hook);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr IntrusiveListHook &ToHook(T &t) noexcept {
|
static constexpr auto &ToHook(T &t) noexcept {
|
||||||
static_assert(std::is_base_of<IntrusiveListHook, T>::value);
|
return static_cast<Hook<T> &>(t);
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr const IntrusiveListHook &ToHook(const T &t) noexcept {
|
static constexpr const auto &ToHook(const T &t) noexcept {
|
||||||
static_assert(std::is_base_of<IntrusiveListHook, T>::value);
|
return static_cast<const Hook<T> &>(t);
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr IntrusiveListNode &ToNode(T &t) noexcept {
|
static constexpr IntrusiveListNode &ToNode(T &t) noexcept {
|
||||||
|
Reference in New Issue
Block a user