首页 > 解决方案 > dynamic_cast 从非模板类到模板子类

问题描述

我有一个非模板类 NC 和一个派生模板类 TC。我想将指向 NC 的指针(可能是指向 TC 实例的指针)转换为 TC 指针。模板的实际类型仅限于例如 bool、int 和 string。

class NC {
...
}

template <typename T>
class TC: public NC {
private:
    T value;
public:
    ...
    void setValue(T value) {
        this->value = value;
    }
}

class UserValueProvider {
public:
    int getValue() const { return 5; }
    bool getValue() const { return true; }
    string getValue() const { return "foobar"; }
}

void setUserValue(UserValueProvider *uvp, NC *obj) {
    auto tobj = dynamic_cast< ? >(obj);        // what goes here?
    if(tobj)
        tobj->setValue(uvp->getValue());
}

显而易见的解决方案是执行 3 次动态转换(对于 int、bool 和 string)并调用专用实例的 setValue。然而我想知道是否可能有另一种解决方案,因为可能的专业化越多,需要的动态演员表就越多,而且它更有可能忘记一个专业化。

标签: c++templatessubclassdynamic-cast

解决方案


这里的一种解决方案是翻转调用,并使用虚函数。但首先,让我们重写UserValueProvider::getValue,因为仅对返回类型进行重载是被禁止的。

class UserValueProvider {
    template <class T> struct tag { };
    int getValue(tag<int>) const { return 5; }
    bool getValue(tag<bool>) const { return true; }
    std::string getValue(tag<std::string>) const { return "foobar"; }

public:
    template <class T>
    T getValue() const {
        return getValue(tag<T>{});
    }
};

现在我们可以调用uvp.getValue<T>()来获取对应的值了。NC接下来,向及其派生类添加一个虚函数:

class NC {
public:
    virtual void setValueFrom(UserValueProvider &uvp) = 0;
};

template <typename T>
class TC: public NC {
private:
    T value;
public:
    void setValue(T value) {
        this->value = value;
    }

    void setValueFrom(UserValueProvider &uvp) override {
        setValue(uvp.getValue<T>());
    }
};

瞧,您可以将您的类型传递UserValueProvider给您的类型擦除NC,它会正确调度。

void setUserValue(UserValueProvider *uvp, NC *obj) {
    obj->setValueFrom(*uvp);
}

在 Wandbox 上现场观看


推荐阅读