为什么一个const指针会被意外转换成bool?

3

我有一个类有两个构造函数。一个是针对 bool 的,另一个是针对 A* 的。

struct B
{
    explicit B(bool b)
    {
      std::cout << "B(bool)" << std::endl;
    }
    explicit B(A*)
    {
      std::cout << "B(A*)" << std::endl;
    }
};

在构造B时,应使用const A*而不是A*-- const A*会转换为bool

const A a;
B b(&a);

输出结果:B(bool)


期望的解决方案是:

编译器错误:“没有B(const A*)的有效构造函数”

我已经尝试使用explicit关键字,但没有起作用。

在coliru上运行的示例


1
如果你将 B(bool) 改为 B(bool&),那么问题也可以解决。或者考虑使用 重复答案 中提到的 type_trait。 - iammilind
谢谢 - 现在我需要找到我们代码库中所有可能的“陷阱”。 - florgeng
我认为这不是重复的 - 建议的重复部分有一个 std :: string 重载。 这非常不同 - 字符串不是内置类型,也不会转换为 bool。 指针会。 - MSalters
@MSalters,这似乎是一个重复问题,因为在链接的问题中,OP期望将 const char* 转换为 std::string。但是这里是 const A *。您还可以参考超级重复问题的链接。请参考OP的[评论](https://dev59.com/zbjna4cB1Zd3GeqP5CSx?noredirect=1#comment104939037_59372958),其中说明链接答案满足查询。 - iammilind
@iammilind:但那是完全不同级别的转换。 - MSalters
1
对我来说,使用链接中的问题是可以的——似乎没有比链接答案和@songyuanyao提到的更好的解决方案。 - florgeng
1个回答

5
我们无法阻止指针到bool的隐式转换( bool conversion);您可以添加另一个重载构造函数,接受const A*,当传递const A*时,它将被选择在overload resolution中,因为它是一个精确匹配,而B::B(bool)需要一个隐式转换。通过将其标记为delete,如果它被选择,则程序变得不合规。
struct B
{
    explicit B(bool b)
    {
      std::cout << "B(bool)" << std::endl;
    }
    explicit B(A*)
    {
      std::cout << "B(A*)" << std::endl;
    }
    B(const A*) = delete;
};

直播

或者你可以标记接受指针类型的重载构造函数 delete,这样所有的指针类型都不能传递给B::B,除了像你所做的那样单独声明构造函数的 A*

template <typename T>
B(T*) = delete;

直播


有可能 - 但是否存在一种解决方案,我不会意外地忘记所有可能的重载? - florgeng
@florgeng 答案已修订。这是你想要的吗? - songyuanyao
1
是的,链接的答案适用于我的问题——不幸的是——无论如何还是谢谢。 - florgeng
通过解释重载解析和隐式转换序列,扩展这个答案可能会很有用。 - MSalters
而且你还需要 explicit B(std::nullptr_t) : B((A*)nullptr) {}。;-) - Jarod42

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接