【发布时间】:2019-11-22 06:42:12
【问题描述】:
这里是简化的问题示例,以 CRTP 为特色:
#include <type_traits>
#include <iostream>
enum ActionTypes {
eInit = 2 << 0,
eUpdate = 2 << 1,
eMultUpdate = 2 << 2
};
template <class Data,
unsigned Actions = eInit|eUpdate|eMultUpdate>
class ActionData
{
template<ActionTypes As /*???*/>
struct action {
static void exec(Data*) { std::cout << "ActionData:: /*dummy*/ exec()\n"; };
static void exec(Data*,int) { std::cout << "ActionData::/*dummy*/ exec(int)\n"; };
};
template<>
struct action < /*???*/ >
{
static void exec(Data*) { /*...*/ };
};
template<>
struct action < /*???*/ >
{
static void exec(Data*, int) { /*...*/ };
};
Data* derived() { return static_cast<Data*>(this); }
protected:
void init() { action<eInit>::exec(derived()); }
void update() { action<eUpdate>::exec(derived()); }
void update(int key) { action<eMultUpdate>::exec(derived()); }
public:
enum Keys { DEFAULT_KEY = -1 };
void call(ActionTypes a, int key = DEFAULT_KEY)
{
switch (a) {
case eInit:
init(); break;
case eUpdate:
if (key == DEFAULT_KEY)
update();
else
case eMultUpdate:
update(key);
}
}
};
class Test : public ActionData<Test, eUpdate>
{
public:
void update() { std::cout << "Test :: update()\n"; }
};
int main()
{
Test actor;
ActionTypes a = eInit;
actor.call(a, 0); // useless here but must be possible.
actor.call(eUpdate, 0);
actor.call(eUpdate);
}
本质上不是所有派生类都可以实现所有处理程序,使用枚举来声明它,并且必须调用处理程序的虚拟版本。问题是,除了单独使用enum 和enable_if 的默认实现之外,不可能选择任何实现,它需要一个非类型参数,这让我感到震惊。
PS。另一个问题是目标平台仅限于 C++98\C++03 或 tr1 C++11(无可变参数模板)。笨拙的接口是在大型 C(不是 C++!)项目中使用函数指针的动态(但不用作这样的)多态架构的遗留物。指针或 vtable 的必要性使系统对程序员的错误不稳定导致 vtable 被覆盖。
【问题讨论】: