ADL 和函數範本查找
函數範本在 C 程式設計中發揮重要作用,可實現程式碼重複使用和通用功能。但是,當使用參數依賴查找 (ADL) 在特定命名空間中尋找函數範本時,會出現一個微妙的限制。
嘗試使用顯式模板參數呼叫函數模板時,該問題就會顯現出來,如以下程式碼所示snippet:
namespace ns { struct foo {}; template<int i> void frob(foo const&) {} void non_template(foo const&) {} } int main() { ns::foo f; non_template(f); // This is fine. frob<0>(f); // This is not. }
此失敗背後的原因源自於C 標準中的特定條款。根據 C 標準 03 14.8.1.6,在使用明確模板參數呼叫函數模板時,ADL 不適用,除非具有該名稱的函數模板在呼叫時可見。
在上面的範例中,有當 frob(f); 時,目前作用域中沒有可見的名為 frob 的函數範本稱為。因此,ADL 不會被觸發,編譯器無法找到所需的函數模板。
為了規避此限制,可以在函數模板之前明確指定命名空間,如下所示:
ns::frob<0>(f);
在這種情況下,ADL 不是必需的,因為函數模板是直接從包含的命名空間呼叫的。
以下程式碼範例進一步說明了 ADL 與函數的行為templates:
namespace A { struct B { }; template<int X> void f(B); } namespace C { template<class T> void f(T t); } void g(A::B b) { f<3>(b); //ill-formed: not a function call A::f<3>(b); //well-formed C::f<3>(b); //ill-formed; argument dependent lookup // applies only to unqualified names using C::f; f<3>(b); //well-formed because C::f is visible; then // A::f is found by argument dependent lookup }
在這個例子中,函數模板 f 在命名空間 A 和 C 中都被定義。建立完成後,編譯器首先檢查目前作用域,發現沒有可見的 f 模板。然後套用 ADL,但由於 f 是非限定名稱,因此它無法在其他命名空間中找到函數模板。
要從命名空間 C 呼叫模板,必須使用 C::f 或 using 指令明確限定名稱如程式碼所示。
以上是為什麼參數依賴查找 (ADL) 在明確實例化函數範本時失敗?的詳細內容。更多資訊請關注PHP中文網其他相關文章!