2017-02-11 52 views
4
#include <iostream> 
#include <vector> 

int main() 
{ 
    // case I: uniform initialization 
    // 
    int ii = 100; 
    // Error: cannot be narrowed from type 'int' to 'double' 
    // in initializer list 
    // 
    double dd{ ii }; 

    // case II: initializer_list 
    // 
    std::vector<double> vecDouble{ 1, 2.2 }; // fine! 

    // case III: initializer_list 
    // 
    std::vector<int> vi = { 1, 2.3 }; // error: double to int narrowing 

    // case IV: intializer_list 
    // cannot be narrowed from type 'int' to 'double' 
    // 
    std::vector<double> vecD2{ ii, 2.2 }; // Error 
} 

爲什麼這裏caseI不接受int來雙重轉換,但caseII允許轉換。爲什麼矢量<double>接受帶整數元素的initializer_list?

+1

沒有不一致。 '1'不是'int',它是一個整型文字。用'ii'代替它,你會看到和'double'一樣的錯誤。 –

+0

@MilesBudnek,謝謝! – q0987

回答

4

長話短說,這是有效的,因爲從int轉換爲double而不是縮小轉換。換句話說,這適用於同樣的原因,下面的代碼工作:

double x = 1; 

編譯器需要構造std::initializer_list<E>對大括號初始化。它知道E的類型爲double,因爲您正在初始化std::vector<double>。這在C++ 11標準的第8.5.4節中有詳細描述。

下面是從節8.5.4.3一個例子:

struct S { 
    S(std::initializer_list<double>); // #1 
    S(const std::string&); // #2 
    // ... 
}; 
const S& r1 = { 1, 2, 3.0 }; // OK: invoke #1 

相同的節定義縮小轉換如下:

收縮轉換是隱式轉換

  • 從浮點型到整數類型或
  • 從long double到double或float,或從double到float,除非源是常量表達式並且轉換後的實際值在可以表示的值的範圍內(即使它不能完全表示)或
  • 從整數類型或非範圍枚舉類型轉換爲浮點類型,除非源代碼是常量表達式,並且轉換後的實際值將適合目標類型並將生成轉換回原始類型時的原始值或
  • 從整數類型或非範圍枚舉類型轉換爲不能表示原始類型的所有值的整數類型,除非源爲常量表達式其整體促銷後的價值將適合目標類型。

這兩個例子與ii落入第三類,即從轉換到intdouble當該源爲一常量表達式。

+2

這回答爲什麼'std :: vector vecDouble {1,2.2};'工作,但不是爲什麼'std :: vector vecD2 {ii,2.2};'不起作用。 –

+0

@MilesBudnek現在它確實:-) – dasblinkenlight

+0

「從int轉換爲double不是縮小轉換」。這與將int轉換爲short一樣是一個縮小的轉換。 –

相關問題