在分配给变体时,我觉得我遗漏了一些关于 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 int
或 bool
.因此,将 1 分配给 v
是编译时错误。如果替代方案是 int
和 bool
,然后是 int
替代将产生完全匹配并且不会有歧义。这个特殊的例子在 C++20 中是固定的:
bool
替代方案被排除在考虑范围之外,因为需要进行缩小转换来初始化 bool
来自 int
的值值(value)。因此,在 C++20 中,此代码将始终分配给 long int
替代方案(如果当前在变体中有 bool
对象,则该对象将被销毁)。
关于c++ - 为什么将 int 分配给 std::variant<long int, ...> 失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67067516/