您可以在指向不同模板类实例的指针之间进行转换吗?

时间:2018-07-26 02:11:44

标签: c++ templates metaprogramming

假设我有一个名为Pool的容器类模板和一个名为PoolObject的抽象类

类模板Pool允许用户创建一个包含特定类型池对象的池。例如:

template<class T, size_t pool_size>
Pool()
{
    // assert that type T is derived from PoolObject

    public:
        int grab(){};
        void release(int object_id){};

    private:
        std::array<T, pool_size> pool_members_;
}

现在让我们说我想创建一些不同的池来管理一些不同的对象类型。

class PoolObject1 : public PoolObject{};
class PoolObject2 : public PoolObject{};
class PoolObject3 : public PoolObject{};
class PoolObject4 : public PoolObject{};

Pool<PoolObject1, 100> pool_1;
Pool<PoolObject2, 100> pool_2;
Pool<PoolObject3, 100> pool_3;
Pool<PoolObject4, 100> pool_4;

现在让我们说我想创建一个用于捕获池对象的工厂函数,以及一个用于释放池对象的销毁函数。一个简单的实现将使用switch语句来确定应使用哪个池。

int factory(int object_type)
{
    switch(object_type)
    {
        case 1:
        return pool_1.grab();

        case 2:
        return pool_2.grab();

        case 3:
        return pool_3.grab();

        case 4:
        return pool_4.grab();

    }
}

虽然简单,但我必须对在这些池上运行的任何方法实施相同的case语句。例如,destroy方法。

void destroy(int object_type, int object_id)
{
    switch(object_type)
    {
        case 1:
        return pool_1.release(object_id);

        case 2:
        return pool_2.release(object_id);

        case 3:
        return pool_3.release(object_id);

        case 4:
        return pool_4.release(object_id);
    }
}

随着定义了更多的对象类型,switch语句不断增长,这将成为管理和更新每种方法的痛苦。

一种更简单的解决方案是拥有一个查找表以获取有问题的池,然后调用适当的方法。

例如,我可以尝试将指向每个池的指针存储在数组中。

std::array<void*, 4> pool_ptrs =
{
    &pool_1,
    &pool_2,
    &pool_3,
    &pool_4
};

有了这个池指针数组,我现在可以重写我的工厂并销毁方法,如下所示:

int factory(int object_type)
{
    return static_cast<Pool*>(pool_ptrs[object_id])->grab();
}

void destroy(int object_type, int object_id)
{
    return static_cast<Pool*>(pool_ptrs[object_id])->destroy(object_id);
}

但是,此代码将无法编译。编译器抱怨我的Pool*缺少模板参数。

所以我知道为什么我的代码无法编译,但是,我不知道合适的解决方案是什么。我本质上想将类模板用作“抽象类”。我不想投射指向Pool<Object1, 100>Pool<Object2, 100>的指针,我只想投射指向Pool的指针

所以我的问题是:您可以在指向不同模板类实例的指针之间进行强制转换吗?

1 个答案:

答案 0 :(得分:2)

答案很简单:

是的,您可以强制转换指针,因为不同的实例共享一个公共基类。就像普通类型一样。您需要添加一个PoolBase。请注意,这不是模板,而是常见的非模板接口。

不,根据运行时条件PoolBase::get(int object_type),不能有PoolObject1返回PoolObject2PoolObject3object_type。返回类型是在编译时确定的。