策略转换仅适用于构造函数

发布于 2024-09-19 00:13:00 字数 1559 浏览 7 评论 0原文

#include "stdafx.h"
#include <exception>

template<class T>
class NoCheck;

template<class T>
class EnforceNotNull
{
public:
    //EnforceNotNull(const NoCheck<T>&){}//<<-----If this is uncommented it works
    static void Check(T* p)
    {
        class NullPtrException : public std::exception
        {
        };

        if (!p)
        {
            throw NullPtrException();
        }
    }
};

template<class T>
class NoCheck
{
public:
    NoCheck(){}
    NoCheck(const NoCheck&){}
    NoCheck(const EnforceNotNull<T>&){}
    operator EnforceNotNull<T>() {return EnforceNotNull<T>();}//<<-----This seams to not do its job
    static void Check(T* p)
    {/*Empty body*/}
};


template<class T, template<class> class CheckingPolicy>
class SmartPtr : public CheckingPolicy<T>
{
public:
    SmartPtr(T* p)
    {
        Check(p);
    }

    template<class T1, template <class> class CheckingPolicy1>
    SmartPtr(const SmartPtr<T1,CheckingPolicy1>& pattern):pointee_(pattern.pointee_),
        CheckingPolicy<T>(pattern)
    {
    }
    T* pointee_;
private:

};

int _tmain(int argc, _TCHAR* argv[])
{

    SmartPtr<int,NoCheck> p1(nullptr);
    SmartPtr<int,EnforceNotNull> p = p1;//I'm trying here to convert NoCheck to    

   // EnforceNotNull but it works for me only if I use ctor, if I use conversion optor   
//(from  


  //  NoCheck to EnforceNotNull) it doesn't work why?
    return 0;
}
#include "stdafx.h"
#include <exception>

template<class T>
class NoCheck;

template<class T>
class EnforceNotNull
{
public:
    //EnforceNotNull(const NoCheck<T>&){}//<<-----If this is uncommented it works
    static void Check(T* p)
    {
        class NullPtrException : public std::exception
        {
        };

        if (!p)
        {
            throw NullPtrException();
        }
    }
};

template<class T>
class NoCheck
{
public:
    NoCheck(){}
    NoCheck(const NoCheck&){}
    NoCheck(const EnforceNotNull<T>&){}
    operator EnforceNotNull<T>() {return EnforceNotNull<T>();}//<<-----This seams to not do its job
    static void Check(T* p)
    {/*Empty body*/}
};


template<class T, template<class> class CheckingPolicy>
class SmartPtr : public CheckingPolicy<T>
{
public:
    SmartPtr(T* p)
    {
        Check(p);
    }

    template<class T1, template <class> class CheckingPolicy1>
    SmartPtr(const SmartPtr<T1,CheckingPolicy1>& pattern):pointee_(pattern.pointee_),
        CheckingPolicy<T>(pattern)
    {
    }
    T* pointee_;
private:

};

int _tmain(int argc, _TCHAR* argv[])
{

    SmartPtr<int,NoCheck> p1(nullptr);
    SmartPtr<int,EnforceNotNull> p = p1;//I'm trying here to convert NoCheck to    

   // EnforceNotNull but it works for me only if I use ctor, if I use conversion optor   
//(from  


  //  NoCheck to EnforceNotNull) it doesn't work why?
    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

多彩岁月 2024-09-26 00:13:00

我根本不明白为什么 SmartPtr 必须从检查策略继承。我也不明白为什么政策本身必须是一个模板。

为什么不简单地:

#include <cstdlib>
#include <exception>

class EnforceNotNull
{
public:
    template <class T>
    static void Check(T* p)
    {
        class NullPtrException : public std::exception
        {
        };

        if (!p)
        {
            throw NullPtrException();
        }
    }
};


class NoCheck
{
public:
    template<class T>
    static void Check(T* p)
    {/*Empty body*/}
};


template<class T, class CheckingPolicy>
class SmartPtr
{
public:
    SmartPtr(T* p)
    {
        CheckingPolicy::Check(p);
    }

    template<class T1, class CheckingPolicy1>
    SmartPtr(const SmartPtr<T1,CheckingPolicy1>& pattern):pointee_(pattern.pointee_)
    {
        CheckingPolicy::Check(pointee_);  //pattern's pointee_ may not pass our check
    }
    T* pointee_;
private:

};

int main()
{

    SmartPtr<int,NoCheck> p1(NULL);
    SmartPtr<int,EnforceNotNull> p = p1;
    return 0;
}

I don't see why the SmartPtr has to be inherited from the checking policy at all. Nor do I see why the policy has to be a template itself.

Why not simply:

#include <cstdlib>
#include <exception>

class EnforceNotNull
{
public:
    template <class T>
    static void Check(T* p)
    {
        class NullPtrException : public std::exception
        {
        };

        if (!p)
        {
            throw NullPtrException();
        }
    }
};


class NoCheck
{
public:
    template<class T>
    static void Check(T* p)
    {/*Empty body*/}
};


template<class T, class CheckingPolicy>
class SmartPtr
{
public:
    SmartPtr(T* p)
    {
        CheckingPolicy::Check(p);
    }

    template<class T1, class CheckingPolicy1>
    SmartPtr(const SmartPtr<T1,CheckingPolicy1>& pattern):pointee_(pattern.pointee_)
    {
        CheckingPolicy::Check(pointee_);  //pattern's pointee_ may not pass our check
    }
    T* pointee_;
private:

};

int main()
{

    SmartPtr<int,NoCheck> p1(NULL);
    SmartPtr<int,EnforceNotNull> p = p1;
    return 0;
}
成熟稳重的好男人 2024-09-26 00:13:00

您的 operator EnforceNotNull() 函数不是 const,因此编译器不会将其包含在可能的转换函数集中。取消注释 EnforceNotNull copy ctor 或在上述函数上添加 const ,您的代码应该可以工作。

Your operator EnforceNotNull<T>() function is not const, so the compiler isn't including it in the set of possible conversion functions. Uncomment EnforceNotNull copy ctor or put a const on the above function and your code should work.

初相遇 2024-09-26 00:13:00

您的代码看起来有点过于复杂。例如,您不必继承策略,除非它关心某些状态,而这不是您的情况。另外,拥有类需要放置访问说明符,因此使用结构可能会更好。

无论如何,智能指针不能被复制,这是主要技巧。您只能转让所有权(动产概念)。所以你的复制构造函数有点不正确。如果这显然是您的意图,您可能仍然拥有它,但请确保您有一些参考计数器。

这是您的代码,已简化并可运行:

#include <cstdio>
#include <cstddef>
#include <exception>

class NullPtrException : public std::exception
{
};

template <typename T>
struct EnforceNotNull
{
    static void Check(T *p)
    {
        if (p == NULL)
        {
            throw NullPtrException();
        }
    }
};

template <typename T>
struct NoCheck
{
    static void Check(T *)
    {
    }
};


template <typename T, template <typename> class CheckingPolicy>
class SmartPtr
{
    T* pointee_;

public:
    SmartPtr (T* p) :
        pointee_ (p)
    {
        CheckingPolicy<T>::Check (pointee_);
    }

    template <typename T1, template <typename> class CheckingPolicy1>
    SmartPtr (SmartPtr<T1, CheckingPolicy1> & pattern) :
        pointee_ (pattern.get ())
    {
        CheckingPolicy<T>::Check (pointee_);
        pattern.release ();
    }

    ~SmartPtr ()
    {
        delete pointee_;
        pointee_ = NULL;
    }

    T *get ()
    {
        return pointee_;
    }

    T *release ()
    {
        T *result = pointee_;
        pointee_ = NULL;
        return result;
    }
};

int main()
{
    try
    {
        printf ("Creating NULL pointer...\n");
        SmartPtr<int, NoCheck> p1 (NULL);
        printf ("Changing policy... \n");
        SmartPtr<int, EnforceNotNull> p = p1;
        printf ("This doesn't work :-(\n");
    }
    catch (const NullPtrException &)
    {
        printf ("GOTCHA!!!\n");
    }
}

以下是您如何使用 MPL 强制转换:

#include <cstdio>
#include <cstddef>
#include <exception>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/or.hpp>

class NullPtrException : public std::exception {};

struct EnforceNotNull
{
    template <typename T>
    static void Check(T *p)
    {
        if (p == NULL)
            throw NullPtrException();
    }
};

struct NoCheck
{
    template <typename T>
    static void Check(T *) {}
};


template <typename T, typename CheckingPolicy>
class SmartPtr
{
    T* p_;

public:
    SmartPtr (T* p) :
        p_ (p)
    {
        CheckingPolicy::Check (p_);
    }

    template <typename T1, typename PolicyT>
    SmartPtr (SmartPtr<T1, PolicyT> & ptr,
              // Enable moving from no checking pointer to any pointer
              // or checking pointer to checking pointer.
              // This makes it impossible to transfer checking to non-checking pointer.
              typename boost::enable_if< boost::mpl::or_ <
              boost::is_same<PolicyT, NoCheck>,
              boost::is_same<PolicyT, CheckingPolicy> > >::type *dummy = NULL) :
        p_ (ptr.get ())
    {
        CheckingPolicy::Check (p_);
        ptr.release ();
    }

    ~SmartPtr ()
    {
        delete p_;
        p_ = NULL;
    }

    T *get () const
    {
        return p_;
    }

    T *release ()
    {
        T *result = p_;
        p_ = NULL;
        return result;
    }
};

int main()
{
    try
    {
        SmartPtr<int, NoCheck> p1 (NULL);
        SmartPtr<int, EnforceNotNull> p2 = p1;
        // SmartPtr<int, NoCheck> p3 = p2; // This will not compile.
    }
    catch (const NullPtrException &)
    {
        printf ("GOTCHA!!!\n");
    }
}

Your code looks a little bit overcomplicated. For example, you don't have to inherit a policy unless it cares some state, which is not your case. Plus, having classes requires putting access specifiers, so you might be better off with structs.

Anyways, smart pointers cannot be copied, that is the main trick. You can only transfer ownership (movable concept). So your copy constructor is a bit incorrect. You may still have it if that is clearly your intent, but make sure you have some reference counter whatsoever.

Here is your code, simplified and working:

#include <cstdio>
#include <cstddef>
#include <exception>

class NullPtrException : public std::exception
{
};

template <typename T>
struct EnforceNotNull
{
    static void Check(T *p)
    {
        if (p == NULL)
        {
            throw NullPtrException();
        }
    }
};

template <typename T>
struct NoCheck
{
    static void Check(T *)
    {
    }
};


template <typename T, template <typename> class CheckingPolicy>
class SmartPtr
{
    T* pointee_;

public:
    SmartPtr (T* p) :
        pointee_ (p)
    {
        CheckingPolicy<T>::Check (pointee_);
    }

    template <typename T1, template <typename> class CheckingPolicy1>
    SmartPtr (SmartPtr<T1, CheckingPolicy1> & pattern) :
        pointee_ (pattern.get ())
    {
        CheckingPolicy<T>::Check (pointee_);
        pattern.release ();
    }

    ~SmartPtr ()
    {
        delete pointee_;
        pointee_ = NULL;
    }

    T *get ()
    {
        return pointee_;
    }

    T *release ()
    {
        T *result = pointee_;
        pointee_ = NULL;
        return result;
    }
};

int main()
{
    try
    {
        printf ("Creating NULL pointer...\n");
        SmartPtr<int, NoCheck> p1 (NULL);
        printf ("Changing policy... \n");
        SmartPtr<int, EnforceNotNull> p = p1;
        printf ("This doesn't work :-(\n");
    }
    catch (const NullPtrException &)
    {
        printf ("GOTCHA!!!\n");
    }
}

Here is how you enforce conversions using MPL:

#include <cstdio>
#include <cstddef>
#include <exception>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/or.hpp>

class NullPtrException : public std::exception {};

struct EnforceNotNull
{
    template <typename T>
    static void Check(T *p)
    {
        if (p == NULL)
            throw NullPtrException();
    }
};

struct NoCheck
{
    template <typename T>
    static void Check(T *) {}
};


template <typename T, typename CheckingPolicy>
class SmartPtr
{
    T* p_;

public:
    SmartPtr (T* p) :
        p_ (p)
    {
        CheckingPolicy::Check (p_);
    }

    template <typename T1, typename PolicyT>
    SmartPtr (SmartPtr<T1, PolicyT> & ptr,
              // Enable moving from no checking pointer to any pointer
              // or checking pointer to checking pointer.
              // This makes it impossible to transfer checking to non-checking pointer.
              typename boost::enable_if< boost::mpl::or_ <
              boost::is_same<PolicyT, NoCheck>,
              boost::is_same<PolicyT, CheckingPolicy> > >::type *dummy = NULL) :
        p_ (ptr.get ())
    {
        CheckingPolicy::Check (p_);
        ptr.release ();
    }

    ~SmartPtr ()
    {
        delete p_;
        p_ = NULL;
    }

    T *get () const
    {
        return p_;
    }

    T *release ()
    {
        T *result = p_;
        p_ = NULL;
        return result;
    }
};

int main()
{
    try
    {
        SmartPtr<int, NoCheck> p1 (NULL);
        SmartPtr<int, EnforceNotNull> p2 = p1;
        // SmartPtr<int, NoCheck> p3 = p2; // This will not compile.
    }
    catch (const NullPtrException &)
    {
        printf ("GOTCHA!!!\n");
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文