調用 cos(int_val) 或 sqrt(int_val) 時,編譯器報錯:call to 'cos' is ambiguous / call to 'sqrt' is ambiguous。
double cos(double);
float cos(float);
long double cos(long double);
// C++11 額外提供
double cos(Integral); // 模板或重載處理整數類型
當實參為 int 時:
int → double(標準轉換)int → float(標準轉換)int → long double(標準轉換)三條轉換路徑等級相同(均為標準轉換),編譯器無法選擇「最佳匹配」,導致歧義。
C++ 重載決議規則:
int→float 可能截斷大整數)| 方法 | 代碼示例 | 優點 | 缺點 |
|---|---|---|---|
| 強制轉型(推薦) | cos(static_cast | 明確意圖、零開銷 | 略顯冗長 |
| 字面量後綴 | cos(n * 1.0) 或 cos(1.0 * n) | 簡潔 | 依賴隱式轉換 |
| 變量聲明為 double | double d = n; cos(d); | 清晰 | 額外變量 |
| 模板包裝 | template | 通用復用 | 過度設計 |
C++11 在
// 標準要求提供等價於 double 版本的整數重載
double cos(int x); // 內部轉為 double
double cos(long x); // 內部轉為 double
// ... 其他整數類型
但:若同時包含
// 1. abs 整數歧義
abs(10); // 錯誤:std::abs(int) vs std::abs(long) vs ::abs(int)
abs(static_cast(10)); // 正確
// 2. pow 整數冪次
pow(2, 10); // 錯誤:pow(double,double) vs pow(float,float) ...
pow(2.0, 10); // 正確
// 3. 自定義重載陷阱
void foo(int);
void foo(double);
foo(3.14f); // float→double 優於 float→int(提升 > 轉換)
GCC/Clang 編譯錯誤信息會列出候選函數:
error: call to 'cos' is ambiguous
note: candidate: double cos(double)
note: candidate: float cos(float)
note: candidate: long double cos(long double)
MSVC 類似。利用 IDE「跳轉到定義」查看重載簽名。
整數實參調用 cos/sqrt 等數學函數導致重載歧義,是因為多條標準轉換序列等級相同。解決核心在於顯式指定目標類型(推薦 static_cast),消除編譯器決議不確定性。這體現了 C++ 強類型、顯式優於隱式的設計哲學,養成「數學函數實參浮點化」習慣,能避開大量隱式轉換陷阱。