[英]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 :
- 轉換構造函數。 如果
Types...
中的每個T_i
存在假想 functionF(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.