首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++模板问题

C++模板问题
EN

Stack Overflow用户
提问于 2009-10-20 23:54:01
回答 1查看 255关注 0票数 3

我定义了一个通用的树节点类,如下所示:

代码语言:javascript
复制
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;

我想通过使子指针类型可定制来使它更通用。例如允许使用智能指针类型。我天真地尝试了一下:

代码语言:javascript
复制
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的回答找到了一个解决方案。对于感兴趣的人,下面是完整的代码示例(欢迎评论)。

EDIT2

我修改了接口,以便在外部始终使用原始指针。

代码语言:javascript
复制
#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;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2009-10-20 16:44:12

不是你想的那样。你应该在这里结合一些继承。尝试这样做,例如:

代码语言:javascript
复制
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‘。

基类型保存实际数据(及其相关功能),派生类保存到其他节点的链接。

对于指针的实际外观,有两个模板策略类,您可以这样使用它们:

代码语言:javascript
复制
GenericNode<int, NormalPointerPolicy> instance;
GenericNode<int, SmartPointerPolicy> instance;

问题(或优势?)这种实现的一个特点是,具有一种指针的节点可以持有具有另一种指针的子节点。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1595647

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档