2014-02-17 26 views
2
#include <bits/stdc++.h> 
using namespace std; 

#define vi vector<int> 
#define vvi vector<vi> 

int main() { 
    vi v(10, -1); 
    vvi vv(10, v); 
    for(int i=0; i<vv.size(); i++){ 
     for(int j=0; j<vv[i].size(); j++){ 
      cout << vv[i][j] << " "; 
     } 
     cout << endl; 
    } 
} 

當我編譯上述代碼聲明爲int矢量的矢量拋出,沒有錯誤報告和它運行良好(see this)。但是當我使用vector < vector < int>>聲明一個向量爲int的向量時,會發生錯誤,因爲我沒有在右尖括號之間放置空格。那麼,爲什麼在#define所做的所有vi替換爲vector<int>vvi以及vector< vector< int>>爲什麼沒有錯誤上使用的#define

+0

預處理可與令牌流,並且兩個'>'是分開的令牌。 –

回答

8

你沒有得到#define方法的錯誤的原因是預處理器智能插入中斷。如果你只通過預處理階段(gcc -E,例如)傳遞代碼,你會看到類似這樣的:

int main() { 
    vector<int> v(10,-1); 
    vector<vector<int> > vv(10,v);   // <<-- see space here. 
    for(int i=0; i<vv.size(); i++){ 
     for(int j=0; j<vv[i].size(); j++){ 
      cout << vv[i][j] << " "; 
     } 
     cout << endl; 
    } 
    return 0; 
} 

原因爲什麼出現這種情況有翻譯的階段,以做由ISO C++標準決定。

C++ 11的第2.2節(a)指出有9個翻譯階段。階段3是將源文件分解爲預處理令牌和空白區。

重要的還有在斷詞,從而使vector<vi>是集預處理標記{vector, <, vi, >}的,它是不宏替換部分給出的簡單文字。雖然一個簡單文本替換:

#define vi vector<int> 
#define vvi vector<vi> 
vvi xyzzy; 

會導致:

vector<vector<int>> xyzzy; 

實際上結束了是預處理標記集:

{vector, <, vector, <, int, >, >, WHITESPACE, xyzzy, ;} 

然後,在階段7,標準狀態:

將每個預處理標記轉換爲標記。

因此,儘管事實上簡單的源代碼讀取可能表明這兩個>令牌沒有重組爲一個。


(一)記住的是,雖然我引用標準的C++ 11的零部件,確保答案是更先進的日期,這個特殊的問題是一個C + +03一個。 C++ 11實際上修復瞭解析器,因此多個>字符將在合理的地方關閉模板參數列表(C++ 03始終將其視爲右移運算符)。

C++11 14.2, section 3指定此:

當解析模板參數列表,第一個非嵌套>被視爲結束符,而不是一個大於運營商。類似地,第一非嵌套>>被視爲兩個連續的但不同的>令牌...

+0

聖牛,我不知道預處理器做到了。 – Mehrdad

+1

在預處理階段後你如何看到代碼?有沒有辦法在Windows上查看預處理代碼? –

+1

@NikunjBanka:http://stackoverflow.com/questions/277258/c-c-source-file-after-preprocessing – paxdiablo

1

出現該錯誤是因爲在C++ 03中,雙角括號被解釋爲右移操作符>>。在C++ 11中,語言被改變了,所以它被解釋爲關閉模板參數,所以它應該在C++ 11模式下無錯地編譯。您可以通過在關閉尖括號之間放置空格來解決此問題,例如, vector<vector<int> >

此外,請勿使用#define來定義類似於此的別名;改爲使用typedef,因爲這正是它的目的。

+0

Adam你說的錯誤將在C++ 11中報告,但我正在使用C++ 4.8.1。然而,我已經在paxdiablo的答案中得到了答案。 –