Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用任意数量的(编译时确定的)容器创建内存池?_C++_Templates_C++11_Variadic Templates_Variadic - Fatal编程技术网

C++ 如何使用任意数量的(编译时确定的)容器创建内存池?

C++ 如何使用任意数量的(编译时确定的)容器创建内存池?,c++,templates,c++11,variadic-templates,variadic,C++,Templates,C++11,Variadic Templates,Variadic,我有一个内存池,看起来是这样的: template<typename TreeType> class LeafMemoryPool { public: void stealNodes(TreeType& tree); Leaf* getNode(); private: std::vector<Leaf*> mLeafs; } 以上所有内容都应该能够在编译时确定。我能用C++模板魔术来解决这个问题吗?< /P> #include <

我有一个内存池,看起来是这样的:

template<typename TreeType>
class LeafMemoryPool
{
public:
    void stealNodes(TreeType& tree);
    Leaf* getNode();
private:
    std::vector<Leaf*> mLeafs;
}
以上所有内容都应该能够在编译时确定。我能用C++模板魔术来解决这个问题吗?< /P> <代码>
#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;
};
#包括 #包括 模板 类内存池 { 公众: //仅当声明了相同类型时,模板才有效 //在上面的三个字母中 模板 空心硬脂节点(树形和树形) { //需要访问正确的std::vector //存储TreeType::Leaf。将调用此函数 //很多,需要在编译时确定 //为了让它有用。 使用leaf_type=typename树型::leaf; 使用vec_type=std::vector; auto&pool=std::get(_leaves); } 模板 typename树型::叶*getNode() { 使用leaf_type=typename树型::leaf; 使用vec_type=std::vector; auto&pool=std::get(_leaves); //池现在是对向量的引用 } 私人: //树型中每个树型一个。 //叶片类型可通过以下公式推断: //typename树型::叶 std::tuple\u leaves; };
是的,可以这样做。我将给你们一个简化版的类的解决方案。您应该能够为您的类简单地调整此解决方案。按照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);
}
#包括
A类{};
B类{};
C类{};
模板类池;
模板
类池:公共池{
公众:
使用pool::stealNodes;
void stealNodes(firstArg和tree)
{
}
私人:
std::向量叶;
};
模板类池{
公众:
void stealNodes();//未定义
};
void foo()
{
游泳池;
A A;
B B;
C C;
池.硬脂节点(a);
硬脂节点池(b);
池.硬脂节点(c);
}

std::tuple将使用MemoryPools=std::tuple执行类似于
模板的操作。两个问题:(1)是否会在编译时绑定
auto&pool
,或者是否完成了任何运行时查找?(2) 将动态对象存储在
std::tuple
?1)编译时,2)一点问题也没有。答案很好,但@Sam的解决方案使
stealNodes
成为一个非模板函数,它提供了更好的错误消息,更好地处理派生的
树型体。@yack我不知道。我认为在调试器中两者都会看起来同样可怕。对于简单的情况,只要它是广泛的。至少这只是一个层次的推导深度。如果添加了其他数据成员/非虚拟函数怎么办?这个相互派生的版本很快就会成为一场噩梦。我已经读了好几遍了,但我仍然不确定到底发生了什么。子类化的目的是什么?以及
pool.stealNodes(a)
如何正确地确定“正确的”
std::vector
?@pingul操作符重载。Sam,
getNode
有点棘手,您可能需要将其包括在内。可能是最派生的
pool
助手,将您的类型重命名为
pool\u impl
,并给
pool
一个
模板typename T::Leaf*getNode(){return getNode(tag);}
?其中
pool\u impl
实现
getNode(tag)
?哦,为了清理它,我将继承从实现中分离出来。类似于
struct simple\u pool
(带有向量和stealNodes函数等)和
struct pool:simple\u pool,pool{使用simple_pool::stealNodes;使用pool::stealNodes;
只是因为错误消息在大多数编译器中更容易阅读。@Yakk我尝试过实现您的建议,但我对模板的了解似乎有点有限。如果可能,请提供一个独立的示例。正如@Yakk前面提到的,
getNode
将很难实现。我通过稍微将函数更改为
void getNode(typename firstArg::Leaf*)来解决这个问题
相反,在这种情况下,运算符重载也会起到一些作用。是否会选择另一种解决方案/更好?据我所知,这是有道理的,因为我必须以某种方式声明我正在寻找的叶的类型。
#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);
}