std::get_if(std::variant)为什么要通过指针而不是值/&/const&获取变量参数,是否有实际的原因?

12

我从未使用过std::get_if,因为它的名称与std::get不同,所以我不明白为什么它的参数应该是一个指针¹(而std::get有一个按引用传递的参数)。


¹如果它也被命名为std::get,那么函数重载将是足够的理由。


是的,我的问题可能与是否绝对需要std:: any_cast()和std:: get_if(std:: variant)接受指针作为参数? 相似,但重点在于那里没有回答涉及std::get_ifstd::get的问题,只有一个评论; 唯一的答案集中在std::any_cast上。


我记得Jason Turner在其中一期的C++ Weekly视频中谈到了这个问题。 - WBuck
1
@xskxzr,不是的,原因我已经在问题中添加了。 - Enlico
3个回答

16
这是因为 get_if 是无异常抛出的,因此永远不会引发异常。为了实现这一点,它必须返回一个指针,以便在访问失败时可以返回 nullptr
由于它返回指针,因此必须获取 variant 的指针。如果它获取 variant 的引用,则必须能够接受 variant&const variant&variant&&const variant&& 的类型,但指针保持限定引用没有意义。
考虑到 get_if 接受 variant&&,那么你返回一个 xvalue 的地址,这是糟糕的。即使 get_if 只允许 variant&const variant&,后者仍然可以接受 variant&& 并返回一个悬空指针。

我真的不理解第二段的解释。 - Enlico
1
假设 get_if 接受引用,当它接受 variant&& 时应该返回什么类型? - 康桓瑋
variant&& 只会绑定到右值,对吗?那么返回 nullptr 不是正确的选择吗? - Enlico
2
@Enlico。这可能是一种选择,但这也意味着即使没有问题返回其地址,get_if(std::move(v))也将返回nullptr - 康桓瑋
就像 unique_ptr.get() 一样,我不认为它在 variant 中更无效的原因。 - apple apple
2
如果需要的话,variant &&问题可以很容易地通过使用= delete重载来解决。 - David Stone

4
据我所知,它基于动态转换逻辑。可能失败的动态转换接受一个指针并返回一个指针。
同样地,可能失败的获取操作接受一个指针并返回一个指针。
但实际上,这似乎只是一个不太重要的小问题。

1

这种设计允许您像这样应用“链式”调用:

struct A : public std::variant<int, float>{};

int main()
{
    std::variant<A, char> f;
    A a;
    static_cast<std::variant<int, float>&>(a) = 10;
    f = a;
    cout << *std::get_if<int>(std::get_if<A>(&f));
    return 0;
}

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