I have created a class which wraps pointers and behaves like a pointer would behave, minus a few cases. It is a lock wrapper class which simply locks before usage of the pointer and unlocks once the pointer usage is done.
It must behave exactly like a pointer EXCEPT in the following cases:
- It cannot be implicitly converted to the pointer type it is pointing to
 - It does not handle any implicit memory allocation/deallocation (it provides a method to delete the pointer to the object)
 - When compared to another wrapper object, it compares their pointers to see if they are the same
 
Here is what I have so far:
template <class PtrType, class LockType>
class ELockWrapper {
public:
    class Proxy {
    public:
        Proxy(PtrType* p, LockType* lock) : ptr(p), mLock(lock)  { mLock->Lock(); }
        ~Proxy()                                                 { mLock->Unlock(); }
        PtrType* operator->()                                    { return ptr; }
        PtrType  operator*()                                     { return *ptr; }
    private:
        PtrType*    ptr;
        LockType*   mLock;
    };
    ELockWrapper()                            : ptr(nullptr), lock(nullptr) {}
    ELockWrapper(nullptr_t t)                 : ELockWrapper()   {}
    ELockWrapper(PtrType *p, LockType* l)     : ptr(p), lock(l)  {}
    ELockWrapper(PtrType *p, LockType& l)     : ptr(p), lock(&l) {}
    ELockWrapper(const ELockWrapper& copy) = default;
    ELockWrapper& operator=(const ELockWrapper& x) = default;
    bool operator==(const ELockWrapper& cmp) { return cmp.ptr == ptr; }
    bool operator!=(const ELockWrapper& cmp) { return !operator==(cmp); }
    bool operator==(PtrType* t)              { return ptr == t; }
    bool operator!=(PtrType* t)              { return ptr != t; }
    bool operator==(bool b)                  { return (ptr && b) || (!ptr && !b); }
    bool operator!=(bool b)                  { return !operator==(b); }
    operator bool() const                    { return ptr; }
    Proxy operator->() {
        return Proxy(ptr, lock);
    }
    PtrType operator*() {
        return *Proxy(ptr, lock);
    }
    void Delete() {
        Proxy(ptr, lock);
        delete ptr;
    }
private:
    PtrType*    ptr;
    LockType*   lock;
};
Here is it in action with some test cases.
Any mistakes/suggestions would be much appreciated.
One quick thing I want to ask: if ANY of the methods on ELockWrapper can be called concurrently, should I wrap each overloaded boolean operator with a lock? I'm thinking perhaps the delete method will be called, which a thread was interrupted in one of the operators might be problematic. Just a confirmation if this is the right thing to do?
Delete()method is probably wrong (can't tell as there is no specification). The current behavior is LOCK, UNLOCK,delete ptr. \$\endgroup\$operator->returns an object with a lock count of one (likely expected) but it does so by locking twice and unlocking once. You may want to implement move semantics. \$\endgroup\$PtrTypeis misleading, as that type is not a pointer. The standard usesvalue_typefor the target of a pointer or reference. \$\endgroup\$Lock()andUnlock()are incompatible function names (due to the capital letter) with the standard C++ library classes. If you simply named themlock()andunlock(), you wouldn't require a wrapper struct just to do so. \$\endgroup\$