C++ lock wrapper class around pointer 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 &lt;class PtrType, class LockType&gt;
class ELockWrapper {
public:
    class Proxy {
    public:
        Proxy(PtrType* p, LockType* lock) : ptr(p), mLock(lock)  { mLock-&gt;Lock(); }
        ~Proxy()                                                 { mLock-&gt;Unlock(); }
        PtrType* operator-&gt;()                                    { 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&amp; l)     : ptr(p), lock(&amp;l) {}
    ELockWrapper(const ELockWrapper&amp; copy) = default;

    ELockWrapper&amp; operator=(const ELockWrapper&amp; x) = default;
    bool operator==(const ELockWrapper&amp; cmp) { return cmp.ptr == ptr; }
    bool operator!=(const ELockWrapper&amp; cmp) { return !operator==(cmp); }
    bool operator==(PtrType* t)              { return ptr == t; }
    bool operator!=(PtrType* t)              { return ptr != t; }
    bool operator==(bool b)                  { return (ptr &amp;&amp; b) || (!ptr &amp;&amp; !b); }
    bool operator!=(bool b)                  { return !operator==(b); }
    operator bool() const                    { return ptr; }

    Proxy operator-&gt;() {
        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?
operator== and operator!= should be const.
You need to #include &lt;cstddef&gt; to use nullptr_t.
You are defaulting the copy constructor and assignment operator, but not the move constructor and move assigment operator. That's fine because the defaults are generated anyway, but it is inconsistent, I think.
What is the point of operator==(bool)?
Proxy should be private. You don't want to have users create Proxys.
ELockWrapper does not actually own the pointer it holds. It is copyable and will just copy the pointer it holds. It also does not create anything or delete anything in the constructor/destructor. Nontheless you provide a Delete member. That seems very wrong to me. You don't know how the memory you point to was aquired, it could be with static storage or an array. In both cases calling Delete would cause undefined behavior. The object creating the pointer with new should also be responsible for deleteing it. Calling Delete on two copies of ELockWrapper also causes undefined behavior.
The fact that the pointer is not owned seems to be a major flaw here anyway. Currently the user of your class needs to gurantee that the object pointed to keeps in scope until all ELockWrapper's holding it are destroyed and then it has to take care of proper deletion. Using it outside of ELockWrapper is not allowed. So why not move the responsibility of managing the pointer to ELockWrapper?
The same holds true for the lock. Currently the user needs to provide a suitable lock and keep it live until no ELockWrapper references it anymore. Why not create the lock/mutex inside the constructor from pointer? Though I realize if you do it like this you need to manage references to the lock and you end up with fully reimplementing std::shared_ptr. Therefore I will just assume that this wrapper is explicitly only about locking and not managing ressource lifetime and that the user is required to run the destructors properly.
operator-&gt; is fine if copy elision is performed (not required in C++11, but in C++17), but operator* is not either way. The Proxy object you create in operator* is destroyed before the function returns. That means that Unlock is called before the caller expression using the pointer ends.
operator* currently returns a copy. It should return a reference. At least that is the usual way this operator is interpreted.
In general the approach with operator* and operator-&gt; has some limitations. You may not call either twice in one expression or you have deadlock. But you are also not allowed to save the pointer returned by operator* or a pointer/reference to the object referred because these are not guarded any more by the lock.
I guess it would be much better to let the caller call a aquire which returns a Proxy. Access to the holding pointer is then only allowed via operator* and operator-&gt; of this Proxy. As soon as Proxy goes out of scope its destructor releases the lock, similar to std::lock_guard.

This still allows the user to misuse a saved reference/pointer to the raw object, but at least more than one usage can me made in the same lock aquisition.

An implementation via C++11 standard library would be similar to this (not tested):

template&lt;typename T, typename Mutex&gt;
class ELockWrapper {
    T* t;
    Mutex* mut;

    class Proxy {
        T* t;
        std::unqiue_lock&lt;Mutex&gt; lock;
        Proxy(ELockWrapper&amp; wr) : t(wr-&gt;t), lock(wr-&gt;mut) { }
        friend ELockWrapper;
    public:
        T&amp; operator*() { return *t; }
        T* operator-&gt;() { return t; }
    };

public:
    ELockWrapper() : t(nullptr), mut(nullptr) {}
    ELockWrapper(nullptr_t) : ELockWrapper() {}
    ELockWrapper(T* t, Mutex* mut) : t(t), mut(mut) {}
    ELockWrapper(T* t, Mutex&amp; mut) : t(t), mut(&amp;mut) {}

    Proxy aquire() { return {*this}; }
};