Re: istream_iterator as argument : why external parentheses neede?
Am 13.10.2011 23:13, schrieb ptyxs:
A probably silly question of mine...
Reading the famous book by Josuttis "The C++ Standard Library", I am
wondering why, in the program given Chapter 6, section 9, page 228,
the external parentheses for the first argument in the set constructor
are needed.
Here is it :
#include<iostream>
#include<string>
#include<algorithm>
#include<iterator>
#include<set>
using namespace std;
int main()
{
set<string> coll((istream_iterator<string>(cin)),
istream_iterator<string>());
copy(coll.begin(),coll.end(),ostream_iterator<string>(cout,"\n"));
}
Yes, this is necessary in C++03, but it can be simpler expressed in
C++11 by writing it as:
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
#include <set>
using namespace std;
int main()
{
set<string> coll(istream_iterator<string>(cin),
istream_iterator<string>{});
copy(coll.begin(),coll.end(),ostream_iterator<string>(cout,"\n"));
}
(Note the pair of braces in the second argument to construct coll)
Why not simply :
#include<iostream>
#include<string>
#include<algorithm>
#include<iterator>
#include<set>
using namespace std;
int main()
{
set<string> coll(istream_iterator<string>(cin),
istream_iterator<string>());
copy(coll.begin(),coll.end(),ostream_iterator<string>(cout,"\n"));
}
Yes, this is the classic "most vexing parse" of C++. The reason for this
code being ill-formed is due to the fact, that the compiler is required
to interpret
set<string> coll(istream_iterator<string>(cin),
istream_iterator<string>());
as a *function* declaration: The name of the function is coll, the
return type is std::set<std::string>, the first parameter type is
std::istream_iterator<std::string> (The first parameter name is cin),
the second parameter type is
std::istream_iterator<std::basic_string<char>>(*)().
The last interpretation is another surprise, because a function type -
istream_iterator<string>() is a function type returning
istream_iterator<string> without any parameter types - is interpreted as
a function pointer if given as function parameter. This rule is similar
to another one, where an array type provided as function parameter
actually represents a parameter of pointer type. E.g.
void foo(int a[2]);
is valid but is equivalent to
void foo(int* a);
These are one of the ugliest aspects of C++. Fortunately the new
extended use cases for braces (as shown above) will often help resolving
such unwanted interpretations.
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]