片段
#include <iostream>
#include <optional>
template <typename T>
struct W {
operator T&() { return *t; }
operator bool() const {
std::cout << "called W bool operator\n";
return t != nullptr;
}
T* t;
};
int main() {
int x = 42;
W<int> w{};
w.t = &x;
if (auto w_value = w) {
std::cout << "w_value " << w_value << "\n";
} else {
std::cout << "w is empty" << "\n";
}
return 0;
}
代码在这里godbolt
我在这里想要的是,inif (auto w_value = w)
w
应该在上下文上可转换为 bool,以便赋值有效。
operator T&() { return *t; }
如果注释掉该行,则此操作将按预期工作。
但是当启用此行时,bool
转换运算符将不会被调用。
有没有办法让这段代码工作,使得如果w
转换为,那么在 if-init 表达式中将分配true
对的引用?t
我可以使用 c++20。
Ted 已经很好地解释了为什么
operator bool() const
不在上下文中调用if
。克服该问题的其他方法
定义一个非
const
过载使用更高版本的 C++ 标准中的 deduced-this 一次性定义所有 const、non-const、volatile、lvalue 和 rvalue 变体
这使得
w_value
有效W<int>
。为了使if (auto w_value = w)
有效,必须使用转换运算符之一,因此编译器将尝试它们并相互权衡。如果两者同样有效,则存在歧义,编译将失败。如果一个转换所需的更改少于另一个,则该转换获胜。operator bool() const
- 使const_cast<const W<int>*>(this)
转换运算符匹配。operator T&()
- 无需添加const
,*this
因此被选中。operator T&()
explicit
如果您愿意,您可以制作operator bool() const
,这通常很好,因为它可以禁止意外转换。我也会制作operator bool() const
explicit
。由于的上下文,operator bool() const
您的示例中仍会选择。bool
唯一的“缺点”是您需要在打印时明确说明想要进行什么
w_value
转换:...这是一件好事。
std::optional
只需添加一个符号即可轻松使用,但它可以使代码更加安全:实例
不幸的是,隐式类型转换在 C++ 中相当糟糕,尤其是重载时。