为什么将int分配给std::variant<longint,…>失败?

在分配给变体时,我觉得我遗漏了一些关于 int 类型提升的明显信息。

在 gcc 9.3.0 版本(Ubuntu 9.3.0-11ubuntu0~18.04.1)上,使用 -std=c++17 编译,以下代码编译失败:

#include <variant>
#include <iostream>

int main()
    {
    std::variant<long int, bool> v;  // works fine if "long" is omitted
    long int sanity = 1;             // verify that we can assign 1 to a long int; works fine

    std::cout << sizeof(sanity) << "n";

    v = 1;                           // compiler error here: why doesn't this assign to the long int variant of v?

    return 0;
    }

错误信息:

error: no match for ‘operator=’ (operand types are ‘std::variant<long int, bool>’ and ‘int’)

使这项工作按预期工作是否有什么神奇之处,而无需在作业中进行显式转换?谢谢!

回答

分配给变体不仅仅是分配给变体中当前活动的类型。相反,右手边的类型用于确定哪种可能的类型(替代项)与右手边的最佳匹配。然后,将该类型分配给。

因此,v = 1;不会自动分配给long int那已经是内在价值v,而是,编译时间计算完成,以确定是否long int或者bool是更好的匹配int(右手边的类型)。最佳匹配是使用重载解析规则确定的。换句话说,我们必须想象存在两个函数

void f(long int);
void f(bool);

并问问自己哪个函数会被调用f(1)。如果long int选择了重载,则v = 1分配给long int对象。如果bool选择了重载,则long int当前在里面的v被销毁,并bool构造一个值为 1的新对象。

不幸的是,这种重载决议是模棱两可的:1需要“积分转换”来匹配long intbool。因此,给 1 赋值v是一个编译时错误。如果备选方案是intbool,那么int备选方案将产生完全匹配并且不会有歧义。

这个特定的例子在 C++20 中是固定的:bool替代方案被排除在考虑之外,因为bool从一个int值初始化一个值需要一个缩小转换。因此,在 C++20 中,此代码将始终分配给long int替代项(如果bool当前在变体中存在对象,则将其销毁)。


以上是为什么将int分配给std::variant&lt;longint,…&gt;失败?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>