簡體   English   中英

標准庫模板中運算符的非限定查找

[英]Unqualified lookup of operators in standard library templates

namespace N {
    struct A {};
    
    template<typename T>
    constexpr bool operator<(const T&, const T&) { return true; }
}

constexpr bool operator<(const N::A&, const N::A&) { return false; }

#include<functional>

int main() {
    static_assert(std::less<N::A>{}({}, {}), "assertion failed");
}

參見https://godbolt.org/z/vsd3qfch6

該程序在看似隨機版本的編譯器上編譯。

自 v19.15 以來,斷言在所有版本的 MSVC 上均失敗,但在 v19.14 上成功。

它在 GCC 11.2 及之前的版本上成功,但在當前的 GCC 中繼上失敗。

它在所有版本的 libstdc++ 上都在 Clang 上失敗。 它在所有版本的 libc++ 中都成功,包括當前主干,版本 13 除外。

ICC 總是成功的。


是否指定了static_assert是否應該成功?


這里的根本問題是std::less在內部使用< ,因為它在模板中使用,所以會從實例化點(這是正確的方法)通過參數相關查找找到operator<重載,但也會通過不合格的名稱從模板定義的角度查找。

如果發現全局重載,則匹配更好。 不幸的是,這使得程序行為依賴於標准庫包含的位置和順序。

我原以為標准庫會禁用std命名空間外的非限定名稱查找,因為無論如何都不能依賴它,但這應該得到保證嗎?

這里重要的是來自std內部的非限定查找是否在到達全局命名空間之前找到任何其他operator< (不管其簽名如何)。 這取決於包含了哪些標頭(任何標准庫 header 都可能包含任何其他標頭),並且還取決於語言版本,因為 C++20許多此類運算符替換為operator<=> 此外,有時這些東西會被重新指定為隱藏的朋友,這些朋友無法通過不合格的查找找到。 無論如何依賴它顯然是不明智的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM