Ошибка реализации clone_ptr - PullRequest
1 голос
/ 01 ноября 2010

У меня есть следующая реализация clone_ptr в попытке сделать безопасные копии указателей объектов, которые необходимо скопировать в классе, поэтому вместо использования конструктора копирования мне посоветовали использовать умные указатели и создать указатель клона .

Реализация Clone_ptr:

#include <algorithm>
#include <functional>
#include <xercesc/dom/DOM.hpp>

struct DOMImplementation_cloner
{
    template <typename T>
    T* operator()(T* pPtr) const
    {
        /* your clone code*/.
        T = DOMImplementationRegistry::getDOMImplementation(X("Core"));
    }
};

struct default_clone
{
    template <typename T>
    T* operator()(T* pPtr) const
    {
        return pPtr->clone();
    }
};

template <typename T, typename Cloner = default_clone>
    class clone_ptr
    {
    public:
        // types
        typedef T element_type;

        typedef element_type value_type;
        typedef const element_type const_value_type;
        typedef value_type* pointer;
        typedef const_value_type* const_pointer;
        typedef value_type& reference;
        typedef const_value_type& const_reference;

        // creation
        clone_ptr() :
        mPtr(0)
        {}

        explicit clone_ptr(pointer pPtr) :
        mPtr(pPtr)
        {}


        clone_ptr(const clone_ptr& pOther) :
        mPtr(pOther.get() ? mCloner(pOther.get()) : 0)
        {}

      /*  clone_ptr(const clone_ptr& pOther) :
        mPtr(pOther.get() ? pOther->clone() : 0),
        {}*/



        clone_ptr& operator=(clone_ptr pOther)
        {
            swap(*this, pOther);

            return *this;
        }

        ~clone_ptr()
        {
            delete get();
        }

        // observers
        pointer get() const
        {
            return mPtr;
        }

        pointer operator->() const
        {
            return get();
        }

        reference operator*() const
        {
            assert(get() != 0);
            return *get();
        }

        // modifiers
        pointer release()
        {
            pointer result = mPtr;
            mPtr = 0;

            return result;
        }

        void reset(pointer pPtr = 0)
        {
            *this = clone_ptr(pPtr);
        }

        // utility
        friend void swap(clone_ptr& pFirst, clone_ptr& pSecond)
        {
            std::swap(pFirst.mPtr, pSecond.mPtr);
        }


        /////////////////////


    // compare
    template <typename T1, typename T2>
    friend bool operator==(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
    {
        return pFirst.get() == pSecond.get();
    }

    template <typename T1, typename T2>
    friend bool operator!=(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
    {
        return !(pFirst == pSecond);
    }

    template <typename T1, typename T2>
    friend bool operator<(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
    {
        return std::less<void*>()(pFirst.get(), pSecond.get());
    }

    template <typename T1, typename T2>
    friend bool operator<=(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
    {
        return !(pFirst > pSecond);
    }

    template <typename T1, typename T2>
    friend bool operator>(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
    {
        return pSecond < pFirst;
    }

    template <typename T1, typename T2>
    friend bool operator>=(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
    {
        return !(pFirst < pSecond);
    }

    template <typename T1>
    friend bool operator!(const clone_ptr<T1>& pX)
    {
        return pX.get() == 0;
    }


    private:
        pointer mPtr;
        default_clone mCloner;
    };

/// Использование указателя xerces для безопасного копирования / клонирования

 private class member:
        clone_ptr<DOMImplementation, DOMImplementation_cloner> impl;

//compiler error:
 error C2039: 'clone' : is not a member of 'xercesc_3_1::DOMImplementation'

Я не понимаю, почему он не использует DOMImplementation_cloner и пытается вместо него использовать default_clone?

Может кто-нибудь уточнить, что я делаю не так?

Ответы [ 2 ]

2 голосов
/ 30 марта 2011

Я рекомендую использовать класс clone_ptr по следующей ссылке: http://www.codeproject.com/KB/stl/clone_ptr.aspx

Указанный выше тип указателя клона не обязательно должен иметь функцию клона. У этого типа класса указателей клонов есть и другие преимущества по сравнению с приведенной выше реализацией типа.

См. Статью для более подробной информации.

2 голосов
/ 01 ноября 2010

Тип клонера жестко задан как default_clone вместо использования параметра шаблона Cloner (см. Последнюю строку определения вашего класса).

Редактировать Просто чтобы убедиться, что вы понимаете, ваше определение mCloner должно выглядеть так:

Cloner mCloner;

Таким образом, клонер будет иметь тип, заданный параметром шаблона.

Еще одна вещь. Если вы ожидаете, что вы clone_ptr будете использовать в более общих настройках (например, коллегами по другим проектам), вы должны сделать тип клонера свойством типа T. Это можно сделать, используя черты типа ( этот ответ дает пример). Это может выглядеть так в вашем clone_ptr:

template< typename T, typename Cloner = cloner_traits< T >::cloner_type >
class clone_ptr {
    // ...
};

Это будет иметь то же поведение по умолчанию, что и ваша текущая реализация. Преимущество состоит в том, что классы, которые требуют специального клонера, просто специализируют шаблон cloner_traits, и пользователю класса не нужно беспокоиться о выборе соответствующего клонера. Если вы все еще хотите переопределить клонер для любого класса, вы все равно можете передать клонер вручную.

...