首页 > 解决方案 > 将抽象类的 n 个实现的静态类型转换为与其动态类型相对应 - 至少使用代码

问题描述

我有一个与演员一起工作的图书馆。Actor 实现的接口在抽象类Actor中定义,并且 Actor-library 与 Actor* 一起使用,但是为了使用另一个库,我需要为每个类实现静态函数,而我的 Actor-library 自然认为每个实现都有Actor 的静态类,所以为了解决这个问题,我为示例情况创建了以下指针变体和包装器:

ActorImpls = std::variant<
    ActorType1*,
    ActorType2*,
    ActorType3*,
    ActorType4*,
>;

以及通过检查动态成员字段将静态类型重新解释为与动态类型相同的强制转换函数:

  ActorImpls staticCorrespond2Dynamic(Actor* cl){
             std::string s = cl->getDynamicName();
                if(s.compare("Dynamic ActorType1")==0){
                    ActorType1* x = reinterpret_cast<ActorType1*>(cl);
                ...

现在我可以使用访问者为给定的 ActorImpls 调用静态函数,但我将始终调用具有相同名称的函数,它将是 ActorType1->staticFunc() 或 ActorType2->staticFunc(),有没有办法使包装器使用更少的代码?

对于静态打印函数,访问者看起来像这样:

struct VisitPrintStatic{
        VisitPrintStatic() {}
        void operator()(ActorType1* x){x->printStaticName();}
        ...

我还尝试过什么:使用可变参数模板实现,主要问题是在运行时获取任何信息几乎是不可能的。有以下类型的函数需要考虑,它们在所有参与者中都具有相同的名称:

Actor* ActorX = new ActorTypeX;
ActorX->staticFunc() //where ActorTypeX must be reinterpreted from Actor* to ActorTypeX*
ActorTypeX::staticFunc(ActorTypeX& obj, Args...) //(same as above)

标签: c++design-patternsc++17

解决方案


是的,您可以使用 C++20 中添加的 'overloaded()' 结构/函数。幸运的是,它的实现非常短,并且可以在 C++17 中运行。

来自以下示例: https ://en.cppreference.com/w/cpp/utility/variant/visit

// helper type for the visitor #4
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; // not needed as of C++20

您的呼叫站点变为:

  std::visit(overloaded {
        [](auto& actor) { StaticFun(actor); },
    }, ActorImpls);

推荐阅读