[英]Using templated member function pointer as template parameter
I have this class: 我有这个课:
#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;
};
Example usage: 用法示例:
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;
}
Is it possible to specify something instead of "???_1" and "???_2" to allow them to be any type? 是否可以指定某些内容而不是“ ??? _ 1”和“ ??? _ 2”以允许它们为任何类型? The goal is to avoid the consumer of this class having to specify DeclaringType and HandlerType explicitly, since they can easily be inferred from subscribeMethod and unsubscribeMethod.
目的是避免此类的使用者必须显式指定DeclaringType和HandlerType,因为可以轻松地从subscriptionMethod和unsubscribeMethod推断出它们。
Note: I cannot use C++17. 注意:我不能使用C ++ 17。
Is it possible to specify something instead of "???_1" and "???_2" to allow them to be any type?
是否可以指定某些内容而不是“ ??? _ 1”和“ ??? _ 2”以允许它们为任何类型?
Not before C++17, no. 不早于C ++ 17,不。 What you're asking for is a template non-type parameter that can deduce its type from the provided value - which is exactly what the new C++17 language feature
template auto
does. 您需要的是一个模板非类型参数,该参数可以从提供的值中推断出其类型-这正是新的C ++ 17语言功能
template auto
执行的操作。
Before C++17, the only way to do such a thing is to provide the type first: 在C ++ 17之前,执行此操作的唯一方法是首先提供类型:
template <class T, T Value> struct X;
So you have to write: 所以你必须写:
EventHandler<decltype(&ExampleEventOwner::Subscribe), &ExampleEventOwner::Subscribe,
decltype(&ExampleEventOwner::Unsubscribe), &ExampleEventOwner::Unsubscribe
> handler;
which, admittedly, sucks. 当然,这很烂。 Alternatively, you could change the design to make the template parameters be the class type and handler type.
另外,您可以更改设计以使模板参数成为类类型和处理程序类型。 This would allow you to write:
这将使您可以编写:
EventHandler<ExampleEventOwner, IEventConsumer> handler(
&ExampleEventOwner::Subscribe, &ExampleEventOwner::Unsubscribe);
which in turn would let you write a factory function: 依次可以让您编写工厂函数:
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);
And that is decidedly non-terrible. 这绝对是不可怕的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.