失败?,c++,c++17,std-variant"/>

首页 > 解决方案 > 为什么将 int 分配给 std::variant失败?

问题描述

在分配给变体时,我觉得我缺少一些关于 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’)

是否有任何魔法可以让这项工作按预期进行,而不需要在作业中进行显式转换?谢谢!

标签: c++c++17std-variant

解决方案


分配给变体并不是简单地分配给变体中当前活动的类型。相反,右手边的类型用于确定哪些可能的类型(替代品)是右手边的最佳匹配。然后,该类型被分配给。

因此,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 intor bool。因此,分配 1v是编译时错误。如果备选方案是intbool,那么int备选方案将产生完全匹配并且不会有歧义。

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


推荐阅读