0

I noticed some weird behavior of c++ vector constructor, can anybody explain it for me? Thanks.

Code snippet 1 works:

#include <string>
#include <vector>
#include <iostream>
#include <istream>
#include <ostream>
#include <iterator>
#include <sstream>
#include <algorithm>

using namespace std;

int main()
{
  string str = "The quick brown fox";

  stringstream strstr(str);

  istream_iterator<string> start(strstr);
  vector<string> results(start, istream_iterator<string>());

  ostream_iterator<string> oit(cout, "\n");
  copy(results.begin(), results.end(), oit);
}

but code snippet 2 doesn't:

#include <string>
#include <vector>
#include <iostream>
#include <istream>
#include <ostream>
#include <iterator>
#include <sstream>
#include <algorithm>

using namespace std;

int main()
{
  string str = "The quick brown fox";

  stringstream strstr(str);

  vector<string> results(istream_iterator<string>(strstr), istream_iterator<string>());

  ostream_iterator<string> oit(cout, "\n");
  copy(results.begin(), results.end(), oit);
}

The only difference is the first parameter in the constructor of the vector.

rick
  • 58
  • 3

2 Answers2

5

Most vexing parse :

 vector<string> results(istream_iterator<string>(strstr), istream_iterator<string>());

Is parsed as a function called results returning a vector and taking one parameter named strstr of type istream_iterator<string> and one unnamed parameter of type "function taking no parameter and returning istream_iterator<string>" .

Change it to :

vector<string> results = vector<string>(istream_iterator<string>(strstr), istream_iterator<string>());

Or you could add parenthesis, but it's not much readable either :

vector<string> results( ( istream_iterator<string>(strstr) ), istream_iterator<string>());

As suggested by BenjaminLindley in the comments, a more readable / less error-prone way is to declare your iterators in separate statements :

auto begin = istream_iterator<string>(strstr);
auto end = istream_iterator<string>();
vector<string> results(begin, end); 

Note:

Some compilers, such as clang, warn on this :

warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]

T.C.
  • 133,968
  • 17
  • 288
  • 421
quantdev
  • 23,517
  • 5
  • 55
  • 88
0

The compiler considers this statement

vector<string> results(istream_iterator<string>(strstr), istream_iterator<string>());

as a function declaration that has return type vector<string> and two parameters, the first of type istream_iterator<string>, and the second of type "function that has return type istream_iterator<string> and no parameters". Use instead either

vector<string> results( ( istream_iterator<string>(strstr) ), istream_iterator<string>());

or

vector<string> results( { istream_iterator<string>(strstr), istream_iterator<string>() } );

That it would be more clear then a declarator may be enclosed in parentheses. So you can write for example

int f( int (x), int (y) );

Or

int ( x ) = 10;
T.C.
  • 133,968
  • 17
  • 288
  • 421
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335