util/Intrusive{List,HashSet}: reimplement hook mode detection with implicit cast
This commit is contained in:
parent
43d633f560
commit
dcd7c6337c
|
@ -25,29 +25,26 @@ struct IntrusiveHashSetHook {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Detect the hook type.
|
|
||||||
*/
|
|
||||||
template<typename U>
|
|
||||||
struct IntrusiveHashSetHookDetection {
|
|
||||||
/* TODO can this be simplified somehow, without checking for
|
|
||||||
all possible enum values? */
|
|
||||||
using type = std::conditional_t<std::is_base_of_v<IntrusiveHashSetHook<IntrusiveHookMode::NORMAL>, U>,
|
|
||||||
IntrusiveHashSetHook<IntrusiveHookMode::NORMAL>,
|
|
||||||
std::conditional_t<std::is_base_of_v<IntrusiveHashSetHook<IntrusiveHookMode::TRACK>, U>,
|
|
||||||
IntrusiveHashSetHook<IntrusiveHookMode::TRACK>,
|
|
||||||
std::conditional_t<std::is_base_of_v<IntrusiveHashSetHook<IntrusiveHookMode::AUTO_UNLINK>, U>,
|
|
||||||
IntrusiveHashSetHook<IntrusiveHookMode::AUTO_UNLINK>,
|
|
||||||
void>>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For classes which embed #IntrusiveHashSetHook as base class.
|
* For classes which embed #IntrusiveHashSetHook as base class.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct IntrusiveHashSetBaseHookTraits {
|
struct IntrusiveHashSetBaseHookTraits {
|
||||||
|
/* a never-called helper function which is used by _Cast() */
|
||||||
|
template<IntrusiveHookMode mode>
|
||||||
|
static constexpr IntrusiveHashSetHook<mode> _Identity(const IntrusiveHashSetHook<mode> &) noexcept;
|
||||||
|
|
||||||
|
/* another never-called helper function which "calls"
|
||||||
|
_Identity(), implicitly casting the item to the
|
||||||
|
IntrusiveHashSetHook specialization; we use this to detect
|
||||||
|
which IntrusiveHashSetHook specialization is used */
|
||||||
template<typename U>
|
template<typename U>
|
||||||
using Hook = typename IntrusiveHashSetHookDetection<U>::type;
|
static constexpr auto _Cast(const U &u) noexcept {
|
||||||
|
return decltype(_Identity(u))();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
using Hook = decltype(_Cast(std::declval<U>()));
|
||||||
|
|
||||||
static constexpr T *Cast(Hook<T> *node) noexcept {
|
static constexpr T *Cast(Hook<T> *node) noexcept {
|
||||||
return static_cast<T *>(node);
|
return static_cast<T *>(node);
|
||||||
|
|
|
@ -77,31 +77,26 @@ using SafeLinkIntrusiveListHook =
|
||||||
using AutoUnlinkIntrusiveListHook =
|
using AutoUnlinkIntrusiveListHook =
|
||||||
IntrusiveListHook<IntrusiveHookMode::AUTO_UNLINK>;
|
IntrusiveListHook<IntrusiveHookMode::AUTO_UNLINK>;
|
||||||
|
|
||||||
/**
|
|
||||||
* Detect the hook type which is embedded in the given type as a base
|
|
||||||
* class. This is a template to postpone the type checks, to allow
|
|
||||||
* forward-declared types.
|
|
||||||
*/
|
|
||||||
template<typename U>
|
|
||||||
struct IntrusiveListHookDetection {
|
|
||||||
/* TODO can this be simplified somehow, without checking for
|
|
||||||
all possible enum values? */
|
|
||||||
using type = std::conditional_t<std::is_base_of_v<IntrusiveListHook<IntrusiveHookMode::NORMAL>, U>,
|
|
||||||
IntrusiveListHook<IntrusiveHookMode::NORMAL>,
|
|
||||||
std::conditional_t<std::is_base_of_v<IntrusiveListHook<IntrusiveHookMode::TRACK>, U>,
|
|
||||||
IntrusiveListHook<IntrusiveHookMode::TRACK>,
|
|
||||||
std::conditional_t<std::is_base_of_v<IntrusiveListHook<IntrusiveHookMode::AUTO_UNLINK>, U>,
|
|
||||||
IntrusiveListHook<IntrusiveHookMode::AUTO_UNLINK>,
|
|
||||||
void>>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For classes which embed #IntrusiveListHook as base class.
|
* For classes which embed #IntrusiveListHook as base class.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct IntrusiveListBaseHookTraits {
|
struct IntrusiveListBaseHookTraits {
|
||||||
|
/* a never-called helper function which is used by _Cast() */
|
||||||
|
template<IntrusiveHookMode mode>
|
||||||
|
static constexpr IntrusiveListHook<mode> _Identity(const IntrusiveListHook<mode> &) noexcept;
|
||||||
|
|
||||||
|
/* another never-called helper function which "calls"
|
||||||
|
_Identity(), implicitly casting the item to the
|
||||||
|
IntrusiveListHook specialization; we use this to detect
|
||||||
|
which IntrusiveListHook specialization is used */
|
||||||
template<typename U>
|
template<typename U>
|
||||||
using Hook = typename IntrusiveListHookDetection<U>::type;
|
static constexpr auto _Cast(const U &u) noexcept {
|
||||||
|
return decltype(_Identity(u))();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
using Hook = decltype(_Cast(std::declval<U>()));
|
||||||
|
|
||||||
static constexpr T *Cast(IntrusiveListNode *node) noexcept {
|
static constexpr T *Cast(IntrusiveListNode *node) noexcept {
|
||||||
auto *hook = &Hook<T>::Cast(*node);
|
auto *hook = &Hook<T>::Cast(*node);
|
||||||
|
|
Loading…
Reference in New Issue