用户定义的指针包装器和 nullptr 比较不会调用我提供的运算符

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

我想比较我的 my_ptr 对象是否是 nullptr。我希望 x == nullptr 调用我提供的以下运算符。

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

但它没有被调用。我没有在输出屏幕上看到“== nullptr called”。而且,如果我取消注释以下行

my_ptr<int> x2{p2}

结果翻转。我在 g++ 和一些在线编译器中检查了这种行为

#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;
}

看到输出

  1. 与 my_ptr x2{p2}; 评论

pointer constructor called

void param called 0

  1. 与 my_ptr x2{p2}; 未评论

pointer constructor called

pointer constructor called

void param called 1

您的接线员有两个问题。

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

它有一个无法从函数参数推导出来的模板参数 U,因此您不能将它与运算符调用语法一起使用 x == y

其次,您定义了 operator==(std::nullptr_t,const my_ptr<V>&) 但您调用了 operator==(const my_ptr<V>&,std::nullptr_t)。在 C++20 之前,您需要显式实现其他顺序,当运算符是对称时也是如此。

你得到预期的输出 operator==:

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

Live Demo

正如 DaveS 所指出的,自 C++20 起,实施 operator(std::nullptr,cosnt my_ptr<V>&) 足以调用 x == nullptr.

最后但同样重要的是,由于在未初始化时使用 pp1,您的代码具有未定义的行为。