diff --git a/src/event/CoarseTimerEvent.hxx b/src/event/CoarseTimerEvent.hxx index 5a75d8b03..8edc10c45 100644 --- a/src/event/CoarseTimerEvent.hxx +++ b/src/event/CoarseTimerEvent.hxx @@ -54,7 +54,7 @@ class EventLoop; class CoarseTimerEvent final : AutoUnlinkIntrusiveListHook { friend class TimerWheel; - friend class IntrusiveList; + friend struct IntrusiveListBaseHookTraits; EventLoop &loop; diff --git a/src/event/DeferEvent.hxx b/src/event/DeferEvent.hxx index a96838656..2f274c33a 100644 --- a/src/event/DeferEvent.hxx +++ b/src/event/DeferEvent.hxx @@ -36,7 +36,7 @@ class EventLoop; class DeferEvent final : AutoUnlinkIntrusiveListHook { friend class EventLoop; - friend class IntrusiveList; + friend struct IntrusiveListBaseHookTraits; EventLoop &loop; diff --git a/src/event/SocketEvent.hxx b/src/event/SocketEvent.hxx index 955a37aa1..69fc7252f 100644 --- a/src/event/SocketEvent.hxx +++ b/src/event/SocketEvent.hxx @@ -46,7 +46,7 @@ class EventLoop; class SocketEvent final : IntrusiveListHook, public EventPollBackendEvents { friend class EventLoop; - friend class IntrusiveList; + friend struct IntrusiveListBaseHookTraits; EventLoop &loop; diff --git a/src/util/IntrusiveList.hxx b/src/util/IntrusiveList.hxx index 938850724..bde879dae 100644 --- a/src/util/IntrusiveList.hxx +++ b/src/util/IntrusiveList.hxx @@ -43,7 +43,8 @@ struct IntrusiveListNode { }; class IntrusiveListHook { - template friend class IntrusiveList; + template friend struct IntrusiveListBaseHookTraits; + template friend class IntrusiveList; protected: IntrusiveListNode siblings; @@ -117,13 +118,14 @@ struct IntrusiveListHookDetection { IntrusiveListHook>; }; +/** + * For classes which embed #IntrusiveListHook as base class. + */ template -class IntrusiveList { +struct IntrusiveListBaseHookTraits { template using Hook = typename IntrusiveListHookDetection::type; - IntrusiveListNode head{&head, &head}; - static constexpr T *Cast(IntrusiveListNode *node) noexcept { auto *hook = &Hook::Cast(*node); return static_cast(hook); @@ -141,6 +143,30 @@ class IntrusiveList { static constexpr const auto &ToHook(const T &t) noexcept { return static_cast &>(t); } +}; + +template> +class IntrusiveList { + template + using Hook = typename IntrusiveListHookDetection::type; + + IntrusiveListNode head{&head, &head}; + + static constexpr T *Cast(IntrusiveListNode *node) noexcept { + return HookTraits::Cast(node); + } + + static constexpr const T *Cast(const IntrusiveListNode *node) noexcept { + return HookTraits::Cast(node); + } + + static constexpr auto &ToHook(T &t) noexcept { + return HookTraits::ToHook(t); + } + + static constexpr const auto &ToHook(const T &t) noexcept { + return HookTraits::ToHook(t); + } static constexpr IntrusiveListNode &ToNode(T &t) noexcept { return ToHook(t).siblings;