基于运行时逻辑调用模板化C++方法

Calling Templated C++ Method based on Runtime Logic

我经常 运行 研究与子类型多态性相关的问题,我正在寻找一个我可能还没有意识到的优雅解决方案。

这是一个简单的继承层次结构:

struct BaseClass { 
    virtual ~BaseClass() = 0; 
    std::string name; 
};

template <T>
struct DerivedClass 
{
    DerivedClass(const std::string& _name): name(_name) { }
};

现在我可能会创建许多具有不同名称和模板类型的 DerivedClass 实例,并使用它们的 BaseClass 将它们存储在一个数组中。

std::vector<BaseClass*> array;
array.push_back(new DerivedClass<TABC>("abc"));
array.push_back(new DerivedClass<TDEF>("def"));
...

这是非常标准的运行时间多态性。

但是,当我有一个要添加特定于类型的新功能层并且不希望这个新层在两个方向上耦合时,我最终不得不做这样的事情:

template <typename T>
void method(DerivedClass<T>* object) { }

void callMethod(BaseClass* object)
{
    // this is the logic I'm trying to move up a layer

    if (object->name == "abc")        method<TABC>(object);
    else if (object->name == "def")   method<TDEF>(object);
}

这些方法中的每一个都必须具有相同的 运行 时间字符串列表才能转换为编译时类型,这意味着添加新类型需要进行大量更改。

如果我假设新层只支持编译时已知的特定选项(无论如何这里都是这种情况),那么在 运行 时添加新类型是可行的,但是不能在这一层使用,没关系。

我目前的想法是,如果我要在class层次结构中引入一个带有函数指针的虚方法,我可以根据特定的编译时间在第二层为每个方法注册函数指针类型(理想情况下只指定一次),有点像双重调度类型方法。

有什么想法、建议吗?

你需要 link 来调用基于字符串的特定模板版本,你能做的最好的就是有一个 string->lambda function 的字典并使用字符串作为查找 function<> 来调用。这避免了嵌套的 ifs 并且它相对容易维护,无论是在编译时(默认列表)还是在运行时(任何更改都只是数组更改)。

我不会抢 Sean Parent 的风头,而是将您带到这个演讲,它将向您展示如何干净、安全和简单地实现这一目标。

该技术称为 'polymorphism as an implementation detail'。它改变了我编写代码的方式。

https://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil