Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

user defined pointer wrapper and nullptr comparison does not call the operator I have provided

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#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

>Solution :

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading