片段
#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;
}
代码在这里godboldt
我在这里想要的是
if (auto w_value = w)
w
应该根据上下文可转换为 bool,以便作业有效。
如果行
operator T&() { return *t; }
被注释掉,这将按预期工作。
但是当启用此行时,
bool
转换运算符将不会被调用。
有没有办法让这段代码工作,这样如果
w
转换为true
,那么对t
的引用将被分配在if-init表达式中?
我有 c++20 可供使用。
if (auto w_value = w)
这使得
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::cout << "w_value " << static_cast<int>(w_value) << "\n";
...这是一件好事。
#include <iostream>
template <typename T>
struct W {
explicit operator T&() {
std::cout << "T&\n";
return *t;
}
explicit 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 " << static_cast<int>(w_value) << '\n';
} else {
std::cout << "w is empty\n";
}
}