簡體   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