[英]Why doesn't narrowing affect overload resolution?
考慮以下:
struct A {
A(float ) { }
A(int ) { }
};
int main() {
A{1.1}; // error: ambiguous
}
這無法編譯,但有關A::A
的模糊重載的錯誤。 兩位候選人都被認為是可行的,因為要求很簡單 :
其次,為了使
F
成為一個可行的函數,每個參數都應存在一個隱式轉換序列(13.3.3.1),它將該參數轉換為F
的相應參數。
雖然存在從double
到int
的隱式轉換序列,但A(int )
重載實際上不可行(在規范的,非C ++標准意義上) - 這將涉及縮小轉換並因此形成錯誤。
為什么在確定可行的候選人的過程中不考慮縮小轉換? 盡管只有一個候選人可行,但是有沒有其他情況下過載被認為是模棱兩可的?
問題在於可以不基於類型檢測縮小轉換的事實。
在C ++中,有很復雜的方法可以在編譯時生成值。
阻止縮小轉換是一件好事。 使C ++的重載分辨率比現在更復雜是一件壞事。
在確定過載分辨率時忽略縮小轉換規則(這使得過載分辨率完全與類型有關),然后在所選過載導致轉換變窄時出錯,使過載分辨率變得更加復雜,並增加了檢測和防止的方法縮小轉換率。
只有一個候選者可行的兩個例子是在實例化期間“遲到”失敗的模板函數,以及復制列表初始化(考慮explicit
構造函數,但如果選擇它們,則會出現錯誤)。 類似地,具有該影響的重載分辨率將使重載分辨率比現在更復雜。
現在,有人可能會問,為什么不將純粹的轉換縮小到類型系統?
縮小轉換純粹是基於類型的轉換是不可行的。 這些更改可能會破壞編譯器可能證明有效的大量“遺留”代碼。 當大多數錯誤是實際錯誤而不是新的編譯器版本是一個混蛋時,掃描代碼庫所需的工作更有價值。
unsigned char buff[]={0xff, 0x00, 0x1f};
這將在基於類型的縮小轉換下失敗,因為0xff
的類型為int
,並且此類代碼非常常見。
如果這樣的代碼需要毫無意義地將int
文字修改為unsigned char
literals,那么我們設置一個標志來告訴編譯器關閉愚蠢的錯誤,那么掃描就會結束。
縮小是編譯器只知道內置類型的東西。 用戶定義的隱式轉換不能標記為縮小。
首先,不應允許縮小轉換。 (不幸的是,這是C兼容性所必需的。在{}
初始化禁止縮小內置類型的情況下,這已得到一定程度的糾正。)
鑒於這些,過載規則無需提及這種特殊情況是有道理的。 這可能是偶然的便利,但並不是那么有價值。 IMO通常會更好地減少重載決策所涉及的因素,並拒絕更多不明確的事情,迫使程序員明確地解決這些問題。
另外,當double不是常量表達式或double太大時,double to float是縮小轉換。
#include <iostream>
#include <iomanip>
int main() {
double d{1.1};
float f{d};
std::cout << std::setprecision(100) << d << " " << f << '\n';
}
這通常會產生錯誤:
main.cpp:7:13: error: non-constant-expression cannot be narrowed from type 'double' to 'float' in initializer list [-Wc++11-narrowing]
float f{d};
^
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.