[英]partial template specialization for template pointer to function
Consider the following abstract Subscription
class: 请考虑以下抽象
Subscription
类:
template <typename TMessage>
class Subscription {
public:
virtual ~Subscription() {}
virtual bool handle(const TMessage &) = 0;
};
In some cases, it could be convenient if one class alone could implement this abstract class several times - even for the same TMessage
- and not force inheritance. 在某些情况下,如果单独一个类可以多次实现此抽象类 - 即使对于相同的
TMessage
- 而不是强制继承,则可能很方便。
To achieve this I am using a template pointer to function in the following way: 为了实现这一点,我使用模板指针以下列方式运行:
template <typename TMessage, typename TCaller, bool(TCaller::*TMethod)(const TMessage &)>
class Invoker : public Subscription<TMessage> {
public:
Invoker(TCaller *caller) :
m_caller(*caller) {
}
virtual bool handle(const TMessage &message) {
return (m_caller.*TMethod)(message);
}
protected:
TCaller &m_caller;
};
This allows creating template-generated implementers of the abstract class like this: 这允许创建模板生成的抽象类的实现,如下所示:
(instead of implementing in several different classes and sharing objects between them): (而不是在几个不同的类中实现并在它们之间共享对象):
struct MyMessage {};
class Logic {
public:
Logic() :
m_subscription1(new Invoker<MyMessage, Logic, &Logic::handleSubscription1>(this)),
m_subscription2(new Invoker<MyMessage, Logic, &Logic::handleSubscription2>(this)) {
}
~Logic() {
delete m_subscription1;
delete m_subscription2;
}
bool handleSubscription1(const MyMessage &message) {
// handle message... uses class members
return true;
}
bool handleSubscription2(const MyMessage &message) {
// handle message... uses class members
return false;
}
private:
Subscription<MyMessage> *m_subscription1;
Subscription<MyMessage> *m_subscription2;
};
The thing is, that I would like to allow the user modules (ie Logic
class) an implementation of a void
handle function as well as a bool
option. 问题是,我想允许用户模块(即
Logic
类)实现void
句柄函数以及bool
选项。
Now, of course I could create 2 different Invoker
classes - one implemented just like in the above code, and another taking a 3rd template argument of a void-returning function: void(TCaller::*TMethod)(const TMessage &)
. 现在,我当然可以创建两个不同的
Invoker
类 - 一个像上面的代码一样实现,另一个使用void返回函数的第三个模板参数: void(TCaller::*TMethod)(const TMessage &)
。 In the handle function of the void returning function I would call the pointered function, and return true. 在void返回函数的handle函数中,我将调用指针函数,并返回true。
But I was wondering it there's a way to use the same Invoker
class name so that the user won't have to match the right Invoker
to the return value of his handle function. 但我想知道有一种方法可以使用相同的
Invoker
类名,这样用户就不必将正确的Invoker
与其句柄函数的返回值相匹配。 Kinda like function overloading - but for template classes. 有点像函数重载 - 但对于模板类。
Of course if I just created two classes with the same name (each taking different return type function template argument), the compiler would scream for redeclaration of template parameter. 当然如果我刚刚创建了两个具有相同名称的类(每个类采用不同的返回类型函数模板参数),编译器会尖叫重新声明模板参数。
So I tried to achieve this with template partial specialization but couldn't figure out a way to define the 3rd template argument without getting a compilation error - I'm not even sure it's the right way to go at it. 所以我尝试使用模板部分特化来实现这一点,但是无法找到一种方法来定义第三个模板参数而不会出现编译错误 - 我甚至不确定这是正确的方法。
When I tried this: 当我尝试这个时:
template <typename TMessage, typename TCaller, typename TMethod>
class Invoker : public Subscription<TMessage> {
};
template <typename TMessage, typename TCaller, bool(TCaller::*TMethod)(const TMessage &)>
class Invoker<TMessage, TCaller, TMethod> {
public:
Invoker(TCaller *caller) :
m_caller(*caller) {
}
virtual bool handle(const TMessage &message) {
return (m_caller.*TMethod)(message);
}
protected:
TCaller &m_caller;
};
template <typename TMessage, typename TCaller, void(TCaller::*TMethod)(const TMessage &)>
class Invoker<TMessage, TCaller, TMethod> {
public:
Invoker(TCaller *caller) :
m_caller(*caller) {
}
virtual bool handle(const TMessage &message) {
(m_caller.*TMethod)(message);
return true;
}
protected:
TCaller &m_caller;
};
I got the following compilation errors on both Invoker implementations: 我在两个Invoker实现上都遇到了以下编译错误:
error: type/value mismatch at argument 3 in template parameter list for template class Invoker
错误:模板类Invoker的模板参数列表中参数3的类型/值不匹配
error: expected a type, got TMethod错误:期望一个类型,得到了TMethod
And the following compilation errors on the Logic class (for each Invoker): Logic类上的以下编译错误(对于每个Invoker):
In constructor Logic::Logic():
在构造函数Logic :: Logic()中:
error: type/value mismatch at argument 3 in template parameter list for template class Invoker错误:模板类Invoker的模板参数列表中参数3的类型/值不匹配
error: expected a type, got &Logic::handleSubscription1错误:期望一个类型,得到&Logic :: handleSubscription1
error: invalid conversion from Logic* const to int错误:从Logic * const到int的无效转换
error: cannot convert int* to Subscription* in initialization错误:初始化时无法将int *转换为Subscription *
What am I doing wrong and is this possible with template partial specialization? 我做错了什么,这可能与模板部分专业化有关吗? If there's any possible solution I would like to know if it's feasible in c++11 as well as c++98.
如果有任何可能的解决方案,我想知道它是否可以在c ++ 11和c ++ 98中使用。
Thanks. 谢谢。
You may do 你可能会这样做
template <typename TMethod, TMethod method> class Invoker;
// partial specialization for TMethod = bool(TCaller::*)(const TMessage &)
template <typename TMessage, typename TCaller, bool(TCaller::*method)(const TMessage &)>
class Invoker<bool(TCaller::*)(const TMessage &), method> :
public Subscription<TMessage>
{
public:
explicit Invoker(TCaller& caller) : m_caller(caller) {}
virtual bool handle(const TMessage &message) {
return (m_caller.*method)(message);
}
protected:
TCaller &m_caller;
};
// partial specialization for TMethod = void(TCaller::*)(const TMessage &)
template <typename TMessage, typename TCaller, void(TCaller::*method)(const TMessage &)>
class Invoker<void(TCaller::*)(const TMessage &), method> :
public Subscription<TMessage>
{
public:
explicit Invoker(TCaller& caller) : m_caller(*caller) {}
virtual bool handle(const TMessage &message) {
(m_caller.*method)(message);
return true;
}
protected:
TCaller &m_caller;
};
And usage is something like: 用法如下:
class Logic {
public:
Logic() :
m_subscription1(std::make_unique<Invoker<decltype(&Logic::handleSubscription1), &Logic::handleSubscription1>>(*this)),
m_subscription2(std::make_unique<Invoker<decltype(&Logic::handleSubscription2), &Logic::handleSubscription2>>(*this)) {
}
bool handleSubscription1(const MyMessage &message) {
// handle message... uses class members
return true;
}
void handleSubscription2(const MyMessage &message) {}
private:
std::unique_ptr<Subscription<MyMessage>> m_subscription1;
std::unique_ptr<Subscription<MyMessage>> m_subscription2;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.