2011-04-14 142 views
7

我最近被一位學生問到關於編譯問題。答案很簡單,但現在我正在努力解決這個問題。 一個簡單的例子:返回參數的類型名查詢

#include <iostream> 
#include <vector> 

struct MyStruct 
{ 
    typedef std::vector<int> MyIntVector; 

    MyIntVector CopyVector(MyIntVector const& vector); 
}; 


MyStruct::MyIntVector MyStruct::CopyVector(MyIntVector const& vector) 
^^^^^^^^ 
{ 
    MyIntVector vec; 
    return vec; 
} 

int main(int /*argc*/, char** /*argv*/) 
{ 
    MyStruct st; 
} 

爲了有效的C++代碼返回參數必須是完全合格的。答案如此之多,並使編譯器/學生感到高興。

但是爲什麼返回值需要用類和函數的參數限定呢?

我總是這樣做,我知道它與ADL查找有關,但現在我被要求尋找更好的答案。
任何人都可以給我一個參考規範或提示,我可以找到更多的信息?

回答

7

語法的結構是這樣的,即返回類型與聲明的內容無關,並且可以聲明(但不定義)具有相同類型的幾件事情。這是有效的C++:

int f(int), g(int); 

因此,具有影響查找類型的聲明對象的確切範圍將是有問題的。在

id1 ns1::f(int), ns2::g(int); 

在哪裏會查找id1?

可以在函數定義中添加特殊規則(可以只有一個函數定義 - 所以不會有歧義 - 但可以是幾個對象),但我不確定可能性已經過檢查,我認爲增加的複雜性不會被優勢所彌補。

+1

而且可以有幾個功能* *的聲明就像你在你的例子顯示。對於朋友的聲明,這實際上也是有效的,在語義上,我認爲:struct C {friend void A :: f(),B :: f(); };'。 – 2011-04-14 12:17:22

3

要繼續解析,編譯器需要弄清楚什麼是類型名,什麼不是。

命名空間範圍內可能發生的唯一一件事是聲明,大多數C++聲明以typename開頭,但C中並不是這種情況。在C程序的頂級範圍內放置一個未定義的標識符聲明它成爲int,static知名度。

無論編譯程序的可能性如何,如果它可以從頭到尾進行,而不需要在類的上下文中進行隊列記號以供稍後識別,那麼解析器也更簡單。

C++ 11解決了拖尾返回類型語法問題:

auto MyStruct::CopyVector(MyIntVector const& vector) -> MyIntVector { 
+0

但請注意,某些聲明不以類型名稱開頭。特別是,'C :: operator int(){}'(轉換函數),'C :: C(){}'(構造函數)和'C ::〜C(){}'(析構函數)以類型名稱開始。它們都以一個聲明符號的命名函數開始。 – 2011-04-14 12:32:46

+0

@Johannes:我想在這個論點中涵蓋更多的內容,因爲有一些明顯的例外,比如'namespace'和存儲類說明符。那肯定出錯了。無論如何,這只是一個稻草人的論點。 – Potatoswatter 2011-04-14 12:46:13