指針衰減與推導模板:解開優先權難題
在C 領域,函數重載與模板推導之間的相互作用可以有時會導致意想不到的結果。當函數被重載以處理陣列和原始指標時,就會出現一個典型的例子。考慮以下程式碼:
template <size_t N> void foo(const char (&s)[N]) { std::cout << "array, size=" << N - 1 << std::endl; } void foo(const char *s) { std::cout << "raw, size=" << strlen(s) << std::endl; }
最初設計用於列印陣列的長度,此函數已擴展為支援非陣列。然而,這個擴展導致了一個令人費解的歧義:
foo("hello") // now prints raw, size=5
為什麼選擇「原始」重載而不是預期的「數組」版本,儘管後者更精確地匹配參數?答案在於一個微妙的概念,稱為指針衰減。
指標衰減是從陣列到其對應指標的隱式轉換。在這種情況下,陣列「hello」會默默地轉換為指向其第一個元素的 const char * 指標。因此,處理指標的重載優先。
此行為源自於 C 中的轉換成本。評估重載以最小化將參數轉換為形參的成本。在這種情況下,數組到指標的轉換比數組到函數參數的轉換成本更低。
要解決此問題,也可以將第二個重載定義為模板:
template <typename T> auto foo(T s) -> std::enable_if_t<std::is_convertible<T, char const *>{}> { std::cout << "raw, size=" << std::strlen(s) << std::endl; }
這種方法確保模板版本是首選,因為它消除了指針衰減轉換。
總之,指針衰減優先於推導模板是重載解決方案中成本最小化原則的結果。為了避免歧義,在重載函數時考慮隱式轉換和重載類型至關重要。
以上是為什麼在 C 重載解析中指標衰減優先於推導模板?的詳細內容。更多資訊請關注PHP中文網其他相關文章!