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++ scanf的一個小知識C++
- C/C++ Const 小知識C++
- 小知識系列:查詢資料庫資料的元資訊資料庫
- MySQL必知必會筆記——查詢的基礎知識MySql筆記
- 7-3 名字查詢與類的作用域
- 幾個SQL查詢小技巧SQL
- python中一些元組知識Python
- 提高 Laravel Eloquent 查詢的5個小技巧Laravel
- MySQL基本知識點梳理和查詢優化MySql優化
- 關於 JavaScript 字串的一個小知識JavaScript字串
- C++知識概要C++
- c++知識點C++
- c++中的查詢list元素C++
- 【C++】C++基礎知識C++
- 【前端詞典】幾個有益的 CSS 小知識前端CSS
- 15個高效的MySQL資料庫查詢小技巧MySql資料庫
- B樹(B-tree, 平衡的多路查詢樹)的相關知識
- Mybatis中的小知識MyBatis
- VEEAM的小知識點
- MySQL--基礎知識點--65--組合查詢MySql
- Mysql常用sql語句(20)- 子查詢重點知識MySql
- sql教程中一些知識的實際擴充套件SQL套件
- Spring框架中一個有用的小元件:Spring RetrySpring框架元件
- C++基本知識點C++
- C++基礎知識C++
- 【C++】 C++知識點總結C++
- 關於前端應該知道的5個小知識前端
- 前端須知的 Cookie 知識小結前端Cookie
- 知識小匯
- Spring小知識Spring
- Python小知識Python
- baota小知識
- 二分查詢(c++)C++
- 折半查詢(C++實現)C++
- 【知識點】C++的日誌框架C++框架
- 前端進階-個人筆記-小知識前端筆記
- 關於集合中一些常考的知識點總結