繁体   English   中英

std::variant 在 MSVC 和 gcc 中的行为不同

[英]std::variant behaves differently in MSVC and gcc

MSVC 19.28 拒绝以下代码,但 gcc 10.2 接受它并输出true false

#include <iostream>
#include <variant>

int main()
{
    std::variant<long long, double> v{ 0 };
    std::cout << std::boolalpha << std::holds_alternative<long long>(v) << ' ' << std::holds_alternative<double>(v) << std::endl;
}

根据cppreference

  1. 转换构造函数。 如果Types...中的每个T_i存在假想 function F(T_i)的重载,则构造一个包含替代类型 T_j 的变体,该替代类型T_j将由表达式F(std::forward<T>(t))的重载决策选择。 Types...同时在 scope 中,除了: 仅当声明T_i x[] = { std::forward<T>(t) };时才考虑重载F(T_i) 对某些发明的变量x有效; 直接初始化包含的值,就像通过来自std::forward<T>(t)的直接非列表初始化一样。

问题被转换为通过重载决议选择F(long long)F(double)的 function 与参数1中的哪个。

int转换为long long是一个整数转换(假设sizeof(long long)大于sizeof(int) ),将int转换为double是一个浮点整数转换,两者的排名都不高于另一个。 所以调用是模棱两可的,程序格式不正确。

MSVC 确实拒绝了该代码,但令我惊讶的是,gcc 接受了它。 此外,在cppreference上也有一个类似的例子:

std::variant<std::string> v("abc"); // OK
std::variant<std::string, std::string> w("abc"); // ill-formed
std::variant<std::string, const char*> x("abc"); // OK, chooses const char*
std::variant<std::string, bool> y("abc"); // OK, chooses string; bool is not a candidate
/* THIS ONE -> */ std::variant<float, long, double> z = 0; // OK, holds long
                                         // float and double are not candidates 

所以我的问题是:是gcc还是MSVC不符合,还是我的理解有误?

在引用的规则中,仅当候选类型的复制列表初始化从参数类型工作时才考虑重载。 此检查不(不能)考虑参数的常量表达式状态,因此任何浮点类型的int都是缩小转换,并且列表初始化不允许(尽管在典型实现中double可以完全表示int的每个值)。 因此,GCC(libstdc++)忽略double选择是正确的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM