簡體   English   中英

為什么在初始化期間應用了用戶定義的轉換?

[英]Why does user-defined conversion applied during the initialization?

以下代碼工作正常:

#include <iostream>

struct B
{
    operator int()
    {
        return int();
    }
};

struct A
{
    A(int, int){ std::cout << "A(int, int)" << std::endl; }
};

A a({B(), B()});

int main()
{ 
}

並產生輸出:

A(int, int)

DEMO

但我不明白為什么? 標准說的是:

但是,在考慮構造函數或用戶定義的轉換函數的參數時,如果在類復制初始化的第二步中復制/移動臨時函數時,通過13.3.1.3調用該函數,則通過13.3.1.7傳遞時初始化程序列表作為單個參數,或者當初始化程序列表只有一個元素並且轉換為某個類X或引用(可能是cv限定的)時,X僅被視為X [...]的構造函數的第一個參數考慮標准轉換序列和省略號轉換序列

所以在我們的例子中,我們考慮了構造函數的參數(它是{B(), B()} )。 更確切地說,我們將initializer-list作為單個參數傳遞(我引用的規則中的第二個案例)。 現在,我們需要將initializer-list的第一個元素(類型B臨時元素)轉換為int ,唯一的方法是應用用戶定義的轉換( B::operator int() )。 但是,正如在規則末尾所說的那樣,我引用標准轉換序列和省略號轉換序列 因為,該代碼不應該工作,它應該拋出像A(int, int)不可行或類型的錯誤。

怎么了。 可能是一個錯誤?

措辭有缺陷,並用C ++ 14改變。 現在[over.best.ics] / 4讀

但是,如果目標是

  • 構造函數的第一個參數或
  • [...]

並且構造函數或用戶定義的轉換函數是候選者

  • 13.3.1.3, 當參數是類拷貝初始化的第二步中的臨時參數時
  • 13.3.1.4,13.3.1.5或13.3.1.6(在所有情況下),或
  • 13.3.1.7的第二階段,當初始化列表只有一個元素,並且目標是類X的構造函數的第一個參數,並且轉換為X或引用(可能是cv-qualified) X

不考慮用戶定義的轉換序列。 [ 注意:這些規則阻止在重載解析期間應用多個用戶定義的轉換,從而避免無限遞歸。 - 結束說明 ]

B()int的轉換不在此范圍內 - 粗體短語僅適用於在復制初始化期間對臨時引用的綁定。
但是, Clang根據以上內容拒絕了此示例代碼

class A;

struct B
{
    operator A();
};

struct A
{
    A(A const&){}
};

A a{B()};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM