我已经定义了一个通用的树节点类,如下所示:
template<class DataType>
class GenericNode
{
public:
GenericNode() {}
GenericNode(const DataType & inData) : mData(inData){}
const DataType & data() const
{ return mData; }
void setData(const DataType & inData)
{ mData = inData; }
size_t getChildCount() const
{ return mChildren.size(); }
const GenericNode * getChild(size_t idx) const
{ return mChildren[idx]; }
GenericNode * getChild(size_t idx)
{ return mChildren[idx]; }
void addChild(GenericNode * inItem)
{ mChildren.push_back(inItem); }
private:
DataType mData;
typedef std::vector<GenericNode*> Children;
Children mChildren;
};
typedef GenericNode<std::string> TreeItemInfo;
我想通过使子指针类型可自定义来使其更通用。例如,允许使用智能指针类型。天真的我试过这个:
template<class DataType, class ChildPtr>
class GenericNode
{
public:
GenericNode() {}
GenericNode(const DataType & inData) : mData(inData){}
const DataType & data() const
{ return mData; }
void setData(const DataType & inData)
{ mData = inData; }
size_t getChildCount() const
{ return mChildren.size(); }
const ChildPtr getChild(size_t idx) const
{ return mChildren[idx]; }
ChildPtr getChild(size_t idx)
{ return mChildren[idx]; }
void addChild(ChildPtr inItem)
{ mChildren.push_back(inItem); }
private:
DataType mData;
typedef std::vector<ChildPtr> Children;
Children mChildren;
};
typedef GenericNode<std::string, GenericNode<std::string > * > TreeItemInfo;
然而,这当然不起作用,因为我需要为第二个参数等第二个参数指定第二个参数......进入永恒。
有没有办法解决这个难题?
我找到了一个基于@Asaf答案的解决方案。对于那些感兴趣的人,下面是一个完整的代码示例(欢迎提出意见)。
我修改了界面,以便始终使用外部原始指针。
#include <string>
#include <vector>
#include <boost/shared_ptr.hpp>
#include <assert.h>
template <class PointeeType>
struct NormalPointerPolicy
{
typedef PointeeType* PointerType;
static PointeeType* getRaw(PointerType p)
{
return p;
}
};
template <class PointeeType>
struct SharedPointerPolicy
{
typedef boost::shared_ptr<PointeeType> PointerType;
static PointeeType* getRaw(PointerType p)
{
return p.get();
}
};
template <class DataType, template <class> class PointerPolicy>
class GenericNode
{
public:
GenericNode() { }
GenericNode(const DataType & inData) : mData(inData) { }
typedef GenericNode<DataType, PointerPolicy> This;
typedef typename PointerPolicy<This>::PointerType ChildPtr;
const This * getChild(size_t idx) const
{ return PointerPolicy<This>::getRaw(mChildren[idx]); }
This * getChild(size_t idx)
{ return PointerPolicy<This>::getRaw(mChildren[idx]); }
void addChild(This * inItem)
{
ChildPtr item(inItem);
mChildren.push_back(item);
}
const DataType & data() const
{ return mData; }
void setData(const DataType & inData)
{ mData = inData; }
private:
DataType mData;
std::vector<ChildPtr> mChildren;
};
typedef GenericNode<std::string, NormalPointerPolicy> SimpleNode;
typedef GenericNode<std::string, SharedPointerPolicy> SmartNode;
int main()
{
SimpleNode simpleNode;
simpleNode.addChild(new SimpleNode("test1"));
simpleNode.addChild(new SimpleNode("test2"));
SimpleNode * a = simpleNode.getChild(0);
assert(a->data() == "test1");
const SimpleNode * b = static_cast<const SimpleNode>(simpleNode).getChild(1);
assert(b->data() == "test2");
SmartNode smartNode;
smartNode.addChild(new SmartNode("test3"));
smartNode.addChild(new SmartNode("test4"));
SmartNode * c = smartNode.getChild(0);
assert(c->data() == "test3");
SmartNode * d = static_cast<const SmartNode>(smartNode).getChild(1);
assert(d->data() == "test4");
return 0;
}
答案 0 :(得分:2)
不是你看待它的方式。你应该在这里结合某种继承。 试试这个,例如:
template <class PointeeType>
struct NormalPointerPolicy
{
typedef PointeeType* PointerType;
};
template <class PointeeType>
struct SmartPointerPolicy
{
typedef MySmartPtrClass<PointeeType> PointerType;
};
template <class DataType>
class BaseGenericNode
{
public:
BaseGenericNode() {}
BaseGenericNode(const DataType & inData) : mData(inData){}
const DataType & data() const
{ return mData; }
void setData(const DataType & inData)
{ mData = inData; }
protected:
DataType mData;
};
template <class DataType, template <class> class PointerPolicy>
class GenericNode : public BaseGenericNode<DataType>
{
typedef typename PointerPolicy<BaseGenericNode<DataType> >::PointerType ChildPtr;
private:
typedef std::vector<ChildPtr> Children;
Children mChildren;
};
GenericNode是实际的节点类型,它包含基类型“BaseGenericNode”
基类型保存实际数据(及其相关功能),派生类保存到其他节点的链接
指针的实际外观有2个模板策略类,你可以这样使用它们:
GenericNode<int, NormalPointerPolicy> instance;
GenericNode<int, SmartPointerPolicy> instance;
这个实现的问题(或优点?)是一个带有一种指针的节点,可以保存带有另一种指针的子节点。