2012-01-19 93 views
5

考慮這個例子:矢量構造函數有兩個參數被解析爲函數聲明

#include <iostream> 
#include <string> 
#include <vector> 
#include <iterator> 

int main() 
{ 
    std::string sen = "abc def ghi jkl"; 
    std::istringstream iss(sen); 

    std::vector<std::string> // declaration in question 
    vec(std::istream_iterator<std::string>(iss), 
     std::istream_iterator<std::string>()); 

    std::copy(vec.begin(), vec.end(), 
       std::ostream_iterator<std::string>(std::cout, "\n")); 
} 

編譯器會引發在調用一個錯誤std::copy

request for member 'begin' in 'vec', which is of non-class type...

我可以避開錯誤像這樣:

std::istream_iterator<std::string> it_begin(iss); 
std::istream_iterator<std::string> it_end; 
std::vector<std::string> vec(it_begin, it_end); 

或通過將括號圍繞每個參數,如下所示:

std::vector<std::string> 
vec((std::istream_iterator<std::string>(iss)), 
    (std::istream_iterator<std::string>())); 

或即使在C++ 11新的統一初始化:

std::vector<std::string> vec { /*begin*/, /*end*/ }; 

爲什麼編譯器解析在該示例中作爲聲明函數聲明?我知道最令人頭痛的解析,但我認爲只發生在空的參數列表中。 我也想知道爲什麼第二種解決方法有效。

+0

GCC 4.6.1,如果有關係。我也嘗試了comeau的在線編譯器。 – jrok

+0

保存自己的一些輸入:'std :: istream_iterator it_begin(iss),it_end; std :: vector vec(it_begin,it_end);' –

+0

格式良好,結構良好且格式良好的問題,符合主題和有用。做得好。 :) –

回答

9

它仍然是最令人煩惱的解析。

std::vector<std::string>      // return type 
vec(          // function name 
    std::istream_iterator<std::string>(iss), // param 1: an iterator called (iss), or just iss 
    std::istream_iterator<std::string>()  // param 2: unnamed function 
);           //   returning iterator 

鷹眼說:

<tomalak> << ETYPE_DESC(vec); std::vector<std::string> vec(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>()); 
<geordi> lvalue function taking a istream_iterator<string, char, char_traits<char>, long> , a pointer to a nullary function returning a istream_iterator<string, char, char_traits<char>, long> , and returning a vector of strings 

問題的癥結所在,真的,那是你的參數名稱可以讓他們加上括號(即iss(iss))不改變聲明的語義。有時。

使用另一組圓括號,它們也圍繞類型,如您所示,強制將第一個參數(因此第二個參數)解析爲表達式而不是聲明。


如果有幫助,也可以考慮:

void foo(int (x)) { 
    cout << x; 
} 

int main() { 
    foo(42); 
} 

Output is 42

+0

@Als:聲明是完全有效的。然而,它既作爲向量聲明也作爲函數聲明是有效的,標準認爲後者優先。這是你的基本[最煩人的解析](http://en.wikipedia.org/wiki/Most_vexing_parse)。 OP很驚訝他的聲明是一個有效的_function_聲明,因爲第一個參數名字周圍的那些parens。 –

+0

Err..Maybe,那些括號是多餘的,無論如何,人們可以把這些括號中的任何一個括起來,它仍然以相同的方式工作。 –

+0

@Als:確實。這纔是重點。順便說一句,複數是「括號」。 –

相關問題