C++中一個名字查詢的小知識
最近看C++標準中的3.4 name lookup章節,碰巧的是stackoverflow也有人提問,他們對這個問題很疑惑,回答的也並不好。
https://stackoverflow.com/questions/25672745/friend-declarations-is-this-a-bug-in-clang
其中C++標準中$3.4.1章節有一個例子:
typedef int f;
namespace N {
struct A {
friend void f(A &);
operator int();
void g(A a) {
int i = f(a);
// f is the typedef, not the friend
// function: equivalent to int(a)
}
};
}
標準上的註解的意思是f最終是一個typedef, 不會使用friend void f(A&)這個函式。
我自己的理解是:
- 在類中宣告的friend函式在普通查詢中,是不可見的,除非在類宣告之前有正式的宣告,也就是說friend宣告不能代替正式的宣告,這是標準所規定的。既然是不可見的,就不會hide掉那個typedef的f。標準$3.3.10講的name hiding在這裡不起作用。
- 名字查詢要是從普通查詢開始的,普通查詢就是從內到外一層層地找,找到一個名字,立馬停止。在這裡找到了f是typedef。普通查詢完成後才有ADL查詢。
- 因為2找到的是typedef,不是一個函式,所以ADL不會介入。ADL是C++11的新規則。如果函式呼叫是非限定的,例如不是: 某namespace::f(a), 某class::f(a), object_ptr->f(a), 或者object.f(a)之類的呼叫,並且引數是使用者定義型別,就會發起ADL,它把函式呼叫中的引數所屬的namespace也拉進來找這個函式f。所以ADL介入的條件是要麼普通查詢找不到這個名字或者找到了而且確實是個函式,那麼就把引數所屬的namespace也拉進來找,最後湊成一個函式集合,做過載解析規則選出最合適的函式。
在這個例子中如果把typedef int f改成 int f()就會發生ADL。普通查詢首先會找到int f(),因為是函式,所以用ADL繼續找,找到void f(A&),編譯器會說”error: void value not ignored as it ought to be”。
這是由於ADL能找到只宣告為friend而沒有正式宣告的函式,標準就是這麼規定。並且void f(A&)比int f()更合適,但是void賦值給 i肯定出錯,所以編譯器報錯啦。
相關文章
- c++ 類作用域中的名字查詢C++
- 名字查詢
- 關於C++ scanf的一個小知識C++
- Perl 知識點查詢
- 小知識系列:查詢資料庫資料的元資訊資料庫
- 獲取查詢塊名字
- 模板中的名字查詢問題
- C++必知的幾個知識點C++
- C/C++ Const 小知識C++
- Excel 的兩個小知識Excel
- 一個不錯的資料倉儲名字查詢網站網站
- MySQL必知必會筆記——查詢的基礎知識MySql筆記
- 幾個SQL查詢小技巧SQL
- 小知識總結-20個
- 7-3 名字查詢與類的作用域
- C++ 查詢某個變數的型別C++變數型別
- 提高 Laravel Eloquent 查詢的5個小技巧Laravel
- 關於 JavaScript 字串的一個小知識JavaScript字串
- 關於redo的幾個小知識點
- MySQL基本知識點梳理和查詢優化MySql優化
- python中一些元組知識Python
- 【前端詞典】幾個有益的 CSS 小知識前端CSS
- 查詢使用者轉儲檔案的名字及位置
- C++知識概要C++
- c++知識點C++
- ROS知識(22)----USB口對映固定名字ROS
- Mybatis中的小知識MyBatis
- VEEAM的小知識點
- 【C++】C++基礎知識C++
- 知識小匯
- iOS小知識iOS
- canvas小知識Canvas
- IPC小知識
- 感冒小知識
- baota小知識
- 絕對的原創-oracle小知識累積-備查用Oracle
- 前端須知的 Cookie 知識小結前端Cookie
- 15個高效的MySQL資料庫查詢小技巧MySql資料庫