从使用了不正确模板类型的基类进行强制转换后,如何保护模板化派生类?

问题描述 投票:0回答:1

我正在尝试编写一个处理 ObjArray 向量的容器,它是一个模板类。 ObjArray 继承自基类,容器包含一个基指针列表,我在操作时将其转换为正确的类型。如何使呼叫者尽可能安全?

下面的代码片段显示了我正在尝试对可能出错的注释执行的操作。

#include <iostream>
#include <vector>
#include <memory>

struct CustomA{
    int a;
};

struct CustomB{
    float b;
};

class IObjArray{
    public:
    virtual void RemoveObj(int obj_id) = 0;
    virtual ~IObjArray() = default;
};

template<typename T>
class ObjArray : public IObjArray{
    public:
    void RemoveObj(int obj_id) override {
        std::cout << "Removing object of id" << obj_id << "\n";
        // Mechanism for removing object from vector below...
    }
    void AddT(T obj){
        vec_of_T_.push_back(obj);
    }
private:
    std::vector<T> vec_of_T_;
};

class ObjManager{
    public:
    template<typename obj>
    size_t RegisterObj(){
        list_.emplace_back(std::make_unique<ObjArray<obj>>());
        return list_.size() - 1;
    }
    
    template<typename T>
    void AddObj(size_t obj_array_id, T obj){
        static_cast<ObjArray<T>*>(list_[obj_array_id].get())->AddT(obj);
    }
    private:
    std::vector<std::unique_ptr<IObjArray>> list_;
};

int main()
{
    ObjManager om;
    auto id_a = om.RegisterObj<CustomA>();
    auto id_b = om.RegisterObj<CustomB>();
    CustomA a{0};
    om.AddObj(id_a, a);
    om.AddObj(id_b, a); // This compiles but is bad. Anyway to stop this happening? Registering a CustomA type in a CustomB ObjArray.
    // om.AddObj<CustomB>(id_b, a); // This doesn't compile because of type mismatch
    return 0;

演示

我可以在注册对象时使用某种形式的 typeid(T) 添加到映射中,然后每当调用 AddObj 时,它都可以将 typeid(T) 作为键键入映射中并拉出正确的 ObjArray。我宁愿使用基于 ID 的系统来索引数组并尽可能快地保持索引。我也无法将方法 AddObj 添加到 IObjArray 接口,因为它们是模板化的。

是否可以解决这些问题,还是让呼叫者意识到这一点很重要?

谢谢!

c++ templates inheritance
1个回答
0
投票

如果

id_a
id_b
可以是不同的类型,您可以将
size_t
索引包装到用元素类型标记的类模板中:

template <typename T>
struct Index {
    size_t value = 0;
    using type = T;
};

class ObjManager{
    public:
    template<typename obj>
    Index<obj> RegisterObj(){
        list_.emplace_back(std::make_unique<ObjArray<obj>>());
        return {list_.size() - 1};
    }
    
    template<typename T>
    void AddObj(Index<T> obj_array_id, T obj){
        static_cast<ObjArray<T>*>(list_[obj_array_id.value].get())->AddT(obj);
    }
    private:
    std::vector<std::unique_ptr<IObjArray>> list_;
};

然后这里:

om.AddObj(id_a, a);
om.AddObj(id_b, a);

第一行编译,而第二行则不编译,因为

Index
id_b
类型与
b
的类型不匹配。

现场演示

© www.soinside.com 2019 - 2024. All rights reserved.