Problem with C ++ Templates

I defined a generic tree-node class as follows:

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;

And I would like to make it more universal by creating a custom child pointer type. For example, to allow the use of a smart pointer type. I naively tried this:

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;

However, this does not work, of course, because I need to specify the second parameter for the second parameter for the second parameter, etc. into eternity.

Is there any way to solve this riddle?

EDIT

I found a solution based on @Asaf's answer. For those interested, the following is a complete code example (comments are welcome).

EDIT2

I changed the interface so that external external pointers are used.

#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;
}
+3
source share
1 answer

, . - . , :

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 - node, BaseGenericNode.
( ), .
, , :

GenericNode<int, NormalPointerPolicy> instance;
GenericNode<int, SmartPointerPolicy> instance;

( ?) , node .

+2

Source: https://habr.com/ru/post/1720580/


All Articles