如何创建具有任意数量(编译时间确定)容器的内存池?
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
,例如 FloatTree
和 Vec3Tree
,并且我为每种树类型创建了一个内存池。然而,传递它们有点烦人,我更喜欢处理所有不同类型的单个内存池。此外,我将来可能需要添加其他类型,我希望它尽可能动态。这可以用可变参数模板来完成吗?我以前从未用过它们,我不知道它们是否可以用于此目的。
我想到的场景可以用伪代码写成
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);
}
我有一个内存池,如下所示:
template<typename TreeType>
class LeafMemoryPool
{
public:
void stealNodes(TreeType& tree);
Leaf* getNode();
private:
std::vector<Leaf*> mLeafs;
}
在我的程序中,我有不同的 TreeType
,例如 FloatTree
和 Vec3Tree
,并且我为每种树类型创建了一个内存池。然而,传递它们有点烦人,我更喜欢处理所有不同类型的单个内存池。此外,我将来可能需要添加其他类型,我希望它尽可能动态。这可以用可变参数模板来完成吗?我以前从未用过它们,我不知道它们是否可以用于此目的。
我想到的场景可以用伪代码写成
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);
}