1
votes

I wrote a smarter pointer class. And to make the following code correct

ZhjSmartPointer<int> a(new int);  
assert(a != NULL); 

I overload the != operator like this:

bool operator !=(T *ptr) const; 

however, this leads to a compile error like this:

ZhjSmartPointer.h:132: note: candidate 1: bool ZhjSmartPointer::operator!=(T*) const [with T = Test] test.cpp:41: note: candidate 2: operator!=(int, int)

I'm confuse with how a ZhjSmartPointer can be transfered into an int

The Code of SmartPointer class is like this:

template <typename T>
class ZhjSmartPointer {
public:
    ZhjSmartPointer();
    explicit ZhjSmartPointer(T *ptr);

    ZhjSmartPointer(const ZhjSmartPointer &smartPtr);
    ZhjSmartPointer &operator =(const ZhjSmartPointer &smartPtr);
    ~ZhjSmartPointer();

    operator bool() const;
    T &operator *() const;
    T *operator ->() const;
    bool operator ==(const ZhjSmartPointer &smartPtr) const;
    bool operator !=(const ZhjSmartPointer &smartPtr) const;

    bool operator ==(T *ptr) const;
    bool operator !=(T *ptr) const;

private:
    void copyPtr(const ZhjSmartPointer &smartPtr);
    void deletePtr();
    T *ptr_;
    size_t *refCnt_;
};

I guess because I overload the 'bool' operator, 'ZhjSmartPointer -> bool -> int' leads to this problem.Is this right?

Sorry,It is just a compile warning, not a error. Someone suggest me not overloading != with parameter(T *), after all, we already have overloaded 'bool'.It will be fine to write codes like these:
ZhjSmartPointer a(new int);
if (a) { ..........
}

2
a constructor taking in a int as parameter without explicit could cause that conversion. - phoeagon
The constructor wouldn't take an int (well T), but a int* (T*), so the "implicit constructor conversion" exists doesn't make much sense. What does make sense is the assumption that you allow an implicit conversion from ZhjSmartPointer<int> to int which would then lead to this error. Really not much you can do, apart from using intptr or removing the implicit conversion. - Voo
As I said in my answer below, it works for me on g++ 4.6.3 with a warning issued. So I guess it is compiler-dependent. What's your compiler? - phoeagon

2 Answers

0
votes

I guess because I overload the 'bool' operator, 'ZhjSmartPointer -> bool -> int' leads to this problem.Is this right?

I think so.

But have you defined any conversion operator for ZhjSmartPointer?

#include <cassert>
#include <cstddef>

template <class T>
class ZhjSmartPointer{
    public:
    ZhjSmartPointer (T* _ptr)
    :ptr_saved(_ptr){    }
    bool operator !=(T *ptr) const{
        return ptr!=ptr_saved;
    }
    private:
    T* ptr_saved;
};
int main(){
    ZhjSmartPointer<int> a(new int);  
    assert(a != NULL);     
}

This compiles for me though (g++ 4.6.3). adding:

    operator bool() const{
        return ptr_saved!=0;
    }

g++ 4.6.3 issues a warning, but still it compiles.

1.cpp:9:14: Candidate 1: bool ZhjSmartPointer<T>::operator!=(T*) const [with T = int]
1.cpp:20:9: Candidate 2: operator!=(int, int) <builtin>

DEPRECATED

Surprisingly NULL is an int, not a void*.

Declaring your constructor like:

ZhjSmartPointer<int> a(new int);  

enables the conversion from int to ZhjSmartPointer. Instead, add an explicit:

explicit ZhjSmartPointer<int> a(new int); 

to suppress this conversion.

1
votes

In C++ NULL is defined as 0, not (void*)0, in fact most textbooks will tell you to use 0 instead of NULL.

If you're using C++11 you should be using nullptr by the way


Your problem is indeed the bool implicit conversion. To fix your problem overload operator not (!) instead.