Home > Software engineering >  user defined pointer wrapper and nullptr comparison does not call the operator I have provided
user defined pointer wrapper and nullptr comparison does not call the operator I have provided

Time:04-21

I want to compare if my my_ptr object is nullptr or not. I expected x == nullptr to call the following operator I have provided.

operator==(std::nullptr_t, const my_ptr<V>& r)

but it is not getting called. I don't see " == nullptr called" displayed on my output screen. And also if I uncomment the following line

my_ptr<int> x2{p2}

the result flips. I checked this behaviour in g and some online compilers

#include <iostream>
#include <type_traits>
#include <utility>

template <typename T>
class my_ptr
{
    T* t = nullptr;

  public:
    my_ptr() 
    {
        std::cout<<"\n No arguments constructor called\n";
    }

    my_ptr(std::nullptr_t) 
    {
        std::cout<<"\n nullptr constructor called\n";
    }

    my_ptr(T* t_)
        : t(t_)
    {
        std::cout<<"\n pointer constructor called\n";
    }
  
    operator const void*() const 
    {
        std::cout<<"\n void param called ";
        return t; 
    }

};

template <typename U, typename V>
bool operator==(const my_ptr<U>& l, const my_ptr<V>& r)
{
    std::cout<<"\n == called\n";
    return l.get() == r.get();
}

template <typename U, typename V>
bool operator==(std::nullptr_t, const my_ptr<V>& r)
{
    std::cout<<"\n == nullptr called\n";
    return false;
}


int main()
{
    int *p;
    my_ptr<int> x{p};
   
    int *p2;
    my_ptr<int> x2{p2}; //uncommenting this line changes the result value
 
    std::cout<<"\n "<<int(x == nullptr)<<"\n";

    return 0;
}

Output seen

  1. with my_ptr x2{p2}; commented

pointer constructor called

void param called 0

  1. with my_ptr x2{p2}; un-commented

pointer constructor called

pointer constructor called

void param called 1

CodePudding user response:

There are two issues with your operator.

template <typename U, typename V>
bool operator==(std::nullptr_t, const my_ptr<V>& r)
{
    std::cout<<"\n == nullptr called\n";
    return false;
}

It has a template argument U that cannot be deduced from the function parameters, hence you cannot use it with operator call syntax x == y.

Second, you defined operator==(std::nullptr_t,const my_ptr<V>&) but you call operator==(const my_ptr<V>&,std::nullptr_t). Before C 20 you need to explicitly implement the other order, also when the operator is symmetric.

You get expected output with this operator==:

template <typename V>
bool operator==(const my_ptr<V>&, std::nullptr_t)
{
    std::cout<<"\n == nullptr called\n";
    return false;
}

Live Demo

As pointed out by DaveS, since C 20, implementing operator(std::nullptr,cosnt my_ptr<V>&) is sufficient to call x == nullptr.

Last but not least, your code has undefined behavior due to using p and p1 when they are uninitialized.

  • Related