[英]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.