Overriding multiple virtual functions in a variadic class template
You cannot put such implementations directly into the class, you have to inherit them (similarly to how Subscriber
inherits from multiple SubscriberImpl
instantiations). However, to override them all and still keep your class polymorphically usable as a Subscriber
, you will have to inherit them "sequentially" instead of "in parallel." Additionally, the Curiously recurring template pattern can be used to give all the implementations access to the final overriding object:
template <class Self, class SubscriberClass, class... ServiceTypes>
struct StatusUpdaterOverride;
template <class Self, class SubscriberClass, class ThisType, class... RemainingTypes>
struct StatusUpdaterOverride<Self, SubscriberClass, ThisType, RemainingTypes...> : StatusUpdaterOverride<Self, SubscriberClass, RemainingTypes...>
{
void handleService(ThisType const& service) override
{
static_cast<Self*>(this)->m_statusUpdater.updateService(service);
}
using StatusUpdaterOverride<Self, SubscriberClass, RemainingTypes...>::handleService;
};
template <class Self, class SubscriberClass, class ThisType>
struct StatusUpdaterOverride<Self, SubscriberClass, ThisType> : SubscriberClass
{
void handleService(ThisType const& service) override
{
static_cast<Self*>(this)->m_statusUpdater.updateService(service);
}
};
template <class StatusUpdatePolicy, class... ServiceType>
struct StatusUpdater : StatusUpdaterOverride<StatusUpdater<StatusUpdatePolicy, ServiceType...>, Subscriber<ServiceType...>, ServiceType...>
{
StatusUpdater(StatusUpdatePolicy const& statusUpdater)
: m_statusUpdater{statusUpdater}
{}
StatusUpdatePolicy m_statusUpdater;
};
[Live example]
I can't see a solution to do exactly what you want. However you can achieve the same behavior without needing the virtual
ity at all. I initially thought about a CRTP solution just like @Angew's answer and then came up with another possibility:
You could edit your Subscriber
class like this:
template <typename ServiceType>
class Subscriber {
public:
template <typename Handler>
void handleService(ServiceType const& service, Handler&& hdler) {
// Maybe give `updateService` a broader name that can extend to other service handlers
std::forward<Handler>(hdler).updateService(service);
}
};
With that, your client code becomes:
template <typename StatusUpdatePolicy, typename... ServiceType>
struct StatusUpdater : Subscriber<ServiceType>...
{
StatusUpdater(StatusUpdatePolicy const& statusUpdater)
: m_statusUpdater{statusUpdater}
{}
template <typename ServiceT>
void handleService(ServiceT const& service) override {
Subscriber<ServiceT>::handleService(service, m_statusUpdater);
}
StatusUpdatePolicy m_statusUpdater;
};