【问题标题】:Vector constructor with two parameters is parsed as a function declaration带两个参数的向量构造函数被解析为函数声明
【发布时间】:2012-02-14 05:21:37
【问题描述】:

考虑这个例子:

#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*/ };

为什么编译器将示例中的声明解析为函数声明?我知道大多数令人烦恼的解析,但我认为这只发生在空参数列表中。 我也想知道为什么第二种解决方法有效。

【问题讨论】:

  • GCC 4.6.1,如果重要的话。我还尝试了 Comeau 的在线编译器。
  • 节省一些打字时间:std::istream_iterator&lt;std::string&gt; it_begin(iss), it_end; std::vector&lt;std::string&gt; vec(it_begin, it_end);
  • 格式良好、结构良好且格式正确的问题,切题且有用。好工作。 :)
  • Most vexing parse(C++) 的可能重复项

标签: c++ parsing stdvector most-vexing-parse


【解决方案1】:

这仍然是最令人头疼的解析。

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

geordi 说:

<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.

【讨论】:

  • @Als:声明完全有效。然而,它作为向量声明和函数声明都是有效的,标准规定后者优先。这是您的基本most vexing parse。 OP 对他的声明是一个有效的 function 声明感到惊讶,因为第一个参数的名称周围有括号。
  • Err..也许,这些括号是多余的,无论如何,一个可以放 n no 这些括号,它仍然会以相同的方式工作。
  • @Als:是的,完全正确。这才是重点。顺便说一句,复数是“括号”。
  • 现在对我来说很有意义。你的第二条评论是对的,我很惊讶这是一个有效的函数声明。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-18
  • 2021-07-21
  • 2013-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多