c++ - 为什么将 int 分配给 std::variant<long int, ...> 失败?

标签 c++ c++17 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’)
使这项工作按预期工作是否有什么神奇之处,而无需在作业中进行显式转换?谢谢!

最佳答案

分配给变体不仅仅是分配给变体中当前事件的类型。相反,右侧的类型用于确定哪种可能的类型(备选方案)与右侧的最佳匹配。然后,将该类型分配给。
因此,v = 1;不会自动分配给 long int已经在里面的值 v ,而是进行编译时计算以确定是否 long intbool更适合 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 的值值(value)。因此,在 C++20 中,此代码将始终分配给 long int替代方案(如果当前在变体中有 bool 对象,则该对象将被销毁)。

关于c++ - 为什么将 int 分配给 std::variant<long int, ...> 失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67067516/

相关文章:

c++ - 是否需要 "nested"释放 std::vector<pair<vector<int>,int>> 中的保留内存以手动释放它?

c++ - 创建基于 SFINAE 的构造函数时出现编译错误

c++ - 将 Boost Spirit 解析器从 boost::variant 转换为 std::variant

c++ - 如果 std::variant 包含 void* 数据,它的析构函数会做什么

c++ - 静态多态和模板容器

c# - 跟踪 GPU 内存泄漏的专业方法(分配而不释放)

c++ - 从访问者更改 boost::variant 基础类型

c++ - 切片 : When passing derived as reference to base, 基引用丢失数据?

c++ - View 和跨步 View 的函数模板特化和 const 噩梦