我有一个 Foo
类,它使用 CRTP 从父类继承模板方法,避免提供大量单独的成员方法。像这样:
class Foo : public SomeBarClass<Foo>
{
//..
//from SomeBarClass
public:
template <class T> void onMsg(T* msg);
private:
IFoxMod* foxMod_;
};
现在,在 onMsg
的实现中,我想要这样的东西:
template <class T>
void Foo::onMsg(T* msg)
{
if (foxMod_->shouldDoStuff(msg))
{
//do stuff
}
}
并且可以有许多 foxMod_
类型(其中一种在 Foo
构造函数中按配置文件中给定的名称实例化)只要它们遵守通用接口(interface)提供一个 bool shouldDoStuff
方法。问题是,这导致我定义以下内容:
struct IFoxMod
{
virtual ~IFoxMod() {}
template <class T> shouldDoStuff(T* msg) = 0;
};
对于要实现的所有 FoxMods
(例如,class redMountainLogic : public IFoxMod
可能有它自己的辨别方式,当它适合做事情时)。
虽然这是非法的,因为不能有虚拟模板,我正试图找到一种解决方法。基本上,我需要动态调度,但我传递的参数是一个模板。我想不出解决方法。
最佳答案
虚函数表似乎与模板特化相处得不好。不足为奇。 VFT 通常基于声明顺序,这在模板中并不存在。一种解决方案是手动重新创建 VFT。
这是一个例子。它可能会更干净一些,但它确实有效。
#include<iostream>
using namespace std;
// Message.h
template<int n>
struct MessageByInt {
typedef int Msg;
};
struct MessageOfHope {
int a;
int b;
static const int id = 0;
};
template<> struct MessageByInt<MessageOfHope::id> { typedef MessageOfHope Msg; };
struct MessageOfDoom {
int b;
int c;
static const int id = 1;
};
template<> struct MessageByInt<MessageOfDoom::id> { typedef MessageOfDoom Msg; };
const int nMessages = 2;
// IFoxMod.h
typedef bool(*callback)(void*);
struct IFoxMod {
callback vtable[nMessages];
template<typename MSG>
bool ShouldDoWork(MSG* msg) {
return vtable[MSG::id](msg);
}
};
template<typename TESTER, int n>
struct filler {
typedef typename MessageByInt<n>::Msg MSG;
typedef typename TESTER::template Tester<MSG> Tester;
static void fill(IFoxMod* impl) {
impl->vtable[n] = reinterpret_cast<callback>(&Tester::ReallyShouldDoWork);
filler<TESTER,n-1>::fill(impl);
}
};
template<typename TESTER>
struct filler<TESTER,-1>{
static void fill(IFoxMod* impl) {
}
};
// RedFox.h
struct RedFoxTester {
template<typename MSG>
struct Tester { // This struct exists to allow partial specialization
static bool ReallyShouldDoWork(MSG* msg) {
return msg->b == 2;
}
};
};
struct RedFoxMod : public IFoxMod {
RedFoxMod() {
filler<RedFoxTester,nMessages-1>::fill(this);
}
};
//Main
main() {
IFoxMod* fm = new RedFoxMod();
MessageOfHope mohb2 = {1, 2};
MessageOfDoom modb2 = {2, 3};
MessageOfHope mohbn2 = {2, 3};
MessageOfDoom modbn2 = {1, 2};
cout << fm->ShouldDoWork(&mohb2) << ", " << fm->ShouldDoWork(&modb2) << endl;
cout << fm->ShouldDoWork(&mohbn2) << ", " << fm->ShouldDoWork(&modbn2) << endl;
}
关于c++ - 如何将参数转发给模板成员函数到 C++ 中的成员基类指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14248153/