如何创建具有任意数量(编译时间确定)容器的内存池?

How to create a memory pool with arbitrary number of (compile time determined) containers?

我有一个内存池,如下所示:

template<typename TreeType>
class LeafMemoryPool
{
public:
    void stealNodes(TreeType& tree);
    Leaf* getNode();
private:
    std::vector<Leaf*> mLeafs;
}

在我的程序中,我有不同的 TreeType,例如 FloatTreeVec3Tree,并且我为每种树类型创建了一个内存池。然而,传递它们有点烦人,我更喜欢处理所有不同类型的单个内存池。此外,我将来可能需要添加其他类型,我希望它尽可能动态。这可以用可变参数模板来完成吗?我以前从未用过它们,我不知道它们是否可以用于此目的。

我想到的场景可以用伪代码写成

template<typename... TreeTypes>
class MemoryPool
{
public:
    // The template is only valid if the same type was declared
    // in TreeTypes above
    template<typename TreeType>
    void stealNodes(TreeType& tree)
    {
        // Somehow need to access the right std::vector that
        // stores TreeType::Leaf. This function will be called
        // a lot, and needs to be determined at compile time
        // for it to be useful.
    }

    template<typename TreeType>
    typename TreeType::Leaf* getNode();
private:
    // One for each TreeType in TreeTypes.
    // The leaf type can be deduced by
    // typename TreeType::Leaf
    std::vector<LeafArg1*> mLeafsForArg1;
    std::vector<LeafArg2*> mLeafsForArg2;
    ...
}

上面的一切应该可以在编译时确定。我可以用一些 C++ 模板魔术来解决这个问题吗?

#include <tuple>
#include <vector>
#include <string>

template<typename... TreeTypes>
class MemoryPool
{
public:
    // The template is only valid if the same type was declared
    // in TreeTypes above
    template<typename TreeType>
    void stealNodes(TreeType& tree)
    {
        // Somehow need to access the right std::vector that
        // stores TreeType::Leaf. This function will be called
        // a lot, and needs to be determined at compile time
        // for it to be useful.
        using leaf_type = typename TreeType::Leaf;
        using vec_type = std::vector<leaf_type>;
        auto& pool = std::get<vec_type>(_leaves);
    }

    template<typename TreeType>
    typename TreeType::Leaf* getNode()
    {
        using leaf_type = typename TreeType::Leaf;
        using vec_type = std::vector<leaf_type>;
        auto& pool = std::get<vec_type>(_leaves);

        // pool is now a reference to your vector
    }
private:
    // One for each TreeType in TreeTypes.
    // The leaf type can be deduced by
    // typename TreeType::Leaf

    std::tuple< std::vector<typename TreeTypes::Leaf> ... > _leaves;
};

是的,可以这样做。我将为您的 class 的简化版本提供解决方案。您应该能够为您的 class 微不足道地调整此解决方案。使用 gcc 6.1.1 测试。

#include <vector>

class A {};
class B {};
class C {};

template<typename ...Args> class pool;

template<typename firstArg, typename ...Args>
class pool<firstArg, Args...> : public pool<Args...> {

 public:

    using pool<Args...>::stealNodes;

    void stealNodes(firstArg &tree)
    {
    }

private:
    std::vector<firstArg *> leafs;

};

template<> class pool<> {

public:

    void stealNodes(); // Undefined
};


void foo()
{
    pool<A, B, C> pool;

    A a;
    B b;
    C c;

    pool.stealNodes(a);
    pool.stealNodes(b);
    pool.stealNodes(c);
}