指針衰減優先於模板推導
在編寫對字串進行操作的程式碼時,通常會遇到嘗試重載的困境同時容納基於數組和非基於數組的字串表示形式的函數可能會導致意外的結果
在此特定場景中,定義了一個初始函數foo 來列印字元陣列的長度:
template <size_t N> void foo(const char (&s)[N]) { std::cout << "array, size=" << N-1 << std::endl; }
此函數接受字元陣列並輸出陣列長度。但是,當擴充 foo 來處理非陣列字串時,會出現歧義:
void foo(const char* s) { std::cout << "raw, size=" << strlen(s) << std::endl; }
目的是讓第二個 foo重載來處理非數組字串,但令人驚訝的是,此擴展導致數組和非數組的原始重載被繞過strings:
foo("hello") // prints raw, size=5
這種意外行為源於指針衰減的概念。數組本質上是指向其第一個元素的指針,將數組轉換為指針是一個非常便宜的操作。因此,編譯器會優先考慮接受指標參數的重載,即使它需要從陣列參數進行隱式轉換。
為了確保所需的行為,其中基於數組的重載用於數組,有必要引入一個額外的重載:
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; }
此重載使用模板推導並將其適用性限制為可轉換為字元指標的類型。透過部分排序,編譯器現在可以根據參數類型正確選擇適當的 foo 函數。
以上是為什麼 C 函數重載中指標衰減會覆蓋模板推導?的詳細內容。更多資訊請關注PHP中文網其他相關文章!