2012-01-19 72 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:确实。这才是重点。顺便说一句,复数是“括号”。 –

相关问题