我有这堂课:
#include <assert.h>
template <typename DeclaringType, typename HandlerType>
using SubscribeMethodType = void (DeclaringType::*)(HandlerType* handler);
template <typename DeclaringType>
using UnsubscribeMethodType = void (DeclaringType::*)();
template <SubscribeMethodType<???_1, ???_2> subscribeMethod, UnsubscribeMethodType<???_1> unsubscribeMethod>
class EventHandler
{
private:
template <typename T>
struct ExtractDeclaringAndHandlerTypes
{
};
template <typename DeclaringType, typename HandlerType>
struct ExtractDeclaringAndHandlerTypes<void (DeclaringType::*)(HandlerType*)>
{
typedef DeclaringType DeclaringType;
typedef HandlerType HandlerType;
};
typedef typename ExtractDeclaringAndHandlerTypes<decltype(subscribeMethod)>::DeclaringType DeclaringType;
typedef typename ExtractDeclaringAndHandlerTypes<decltype(subscribeMethod)>::HandlerType HandlerType;
public:
EventHandler() { }
~EventHandler()
{
Unsubscribe();
}
void Subscribe(DeclaringType* eventOwner, HandlerType* handler)
{
assert(!m_IsSubscribed);
m_EventOwner = eventOwner;
(eventOwner->*subscribeMethod)(handler);
m_IsSubscribed = true;
}
void Unsubscribe()
{
if (m_IsSubscribed)
{
(m_EventOwner->*unsubscribeMethod)();
m_IsSubscribed = false;
}
}
private:
DeclaringType* m_EventOwner;
bool m_IsSubscribed;
};
使用示例:
class IEventConsumer
{
};
class ExampleEventOwner
{
public:
void Subscribe(IEventConsumer* consumer) {}
void Unsubscribe() {}
};
int main()
{
ExampleEventOwner owner;
IEventConsumer consumer;
EventHandler<&ExampleEventOwner::Subscribe, &ExampleEventOwner::Unsubscribe> handler;
handler.Subscribe(&owner, &consumer);
handler.Unsubscribe();
return 0;
}
是否可以指定某些内容而不是“??? _ 1”和“??? _ 2”以允许它们为任何类型?目标是避免此类的使用者必须明确指定DeclaringType和HandlerType,因为可以从subscribeMethod和unsubscribeMethod轻松推断出它们。
注意:我不能使用C ++ 17。
答案 0 :(得分:1)
是否可以指定一些东西而不是&#34; ??? _ 1&#34;和&#34; ??? _ 2&#34;允许他们成为任何类型?
不是在C ++ 17之前,没有。你要求的是一个模板非类型参数,它可以从提供的值中推断出它的类型 - 这正是新的C ++ 17语言特性template auto
所做的。
在C ++ 17之前,做这种事情的唯一方法是首先提供类型:
template <class T, T Value> struct X;
所以你必须写:
EventHandler<decltype(&ExampleEventOwner::Subscribe), &ExampleEventOwner::Subscribe,
decltype(&ExampleEventOwner::Unsubscribe), &ExampleEventOwner::Unsubscribe
> handler;
不可否认,这很糟糕。或者,您可以更改设计以使模板参数成为类类型和处理程序类型。这将允许你写:
EventHandler<ExampleEventOwner, IEventConsumer> handler(
&ExampleEventOwner::Subscribe, &ExampleEventOwner::Unsubscribe);
反过来会让你写一个工厂函数:
template <class T, class H>
EventHandler<void (T::*)(H*), void(T::*)()> makeEventHandler(
void (T::*subscribe)(H*), void (T::*unsubscribe)());
auto handler = makeEventHandler(&ExampleEventOwner::Subscribe,
&ExampleEventOwner::Unsubscribe);
这绝对不可怕。