if init 表达式的转换运算符和布尔运算符

问题描述 投票:0回答:1

片段

#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 可供使用。

c++ if-statement operator-overloading implicit-conversion
1个回答
1
投票
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";
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.