指针类型运算符 VS const bool 运算符优先级

pointer type operator VS const bool operator precedence

#include <cstdint>
#include <iostream>

struct a_struct {
    int64_t* le_int;
    bool not_ok;

    a_struct() : le_int{ new int64_t(0) }, not_ok{ false } {}
    ~a_struct() { delete le_int; }

    operator bool() const {
        return !not_ok;
    }

    operator int64_t* () {
        return le_int;
    }
};

int main(int argc, char** argv) {

    a_struct s;
    s.not_ok = true;
    if (!s)//<-
        std::cout << "o no." << std::endl;

    else if (s.not_ok)
        std::cout << "waddu heck?" << std::endl;

    return 0;
}

在此示例中,!s 分辨率更喜欢 int64_t*() 运算符,而不是 const bool() 运算符。

为什么?

由于您的对象 s 不是 const,因此它更喜欢 non-const 调用类型转换运算符的方式。因此,从 bool 类型转换运算符中删除 const 就可以了。

这是重载决议的“通过转换函数初始化”的情况:http://eel.is/c++draft/over.match.conv

两个转换函数都是候选函数,因为它们都是 non-explicit 并且它们的 return 类型可以隐式转换为 bool。然后使用对象表达式 s 作为参数执行重载解析,并将转换函数的隐含对象参数作为参数。隐含对象参数的类型为 T cv &,其中 T 是 class.

T& 绑定到 T 比将 T const& 绑定到 T 更好。这是对隐式转换序列进行排名的规则之一。 http://eel.is/c++draft/over.ics.rank#3.2.6

请注意,有一个涉及 return 类型转换函数的 tie-breaker 规则。这样的 tie-breaker 规则仅在每个参数的隐式转换序列排名未能产生最佳可行函数后才考虑,因为每个参数的隐式转换序列既不比相应的隐式转换序列好也不差另一个函数的参数。因此,只有当两个转换函数具有相同的 cv-qualification(导致隐含对象参数的相同隐式转换序列)时,才会达到 tie-breaker。 http://eel.is/c++draft/over.match.best#general-2.2