我有一个看起来像这样的内存池:
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 ++模板魔术来解决这个问题吗?
答案 0 :(得分:3)
是的,可以这样做。我将为您提供一个简化版课程的解决方案。您应该能够为您的班级轻松调整此解决方案。用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);
}
答案 1 :(得分:1)
#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;
};