Errors [redacted] from Comeau online:
ComeauTest.c(47): error: qualified name is not allowed
std::vector<line_t> v(std::istream_iterator<line_t>
(std::cin),
^
ComeauTest.c(49): error: expression must have class type
std::sort(v.begin(), v.end());
^
ComeauTest.c(49): error: expression must have class type
std::sort(v.begin(), v.end());
^
[large numbers of STL errors redacted]
-----------------------
#include <iostream>
#include <ostream>
#include <istream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
class line_t
{
private:
std::string s;
public:
friend std::istream& operator>>(std::istream& is, line_t& l)
{
return std::getline(is, l.s);
}
friend std::ostream& operator<<(std::ostream& os, const line_t& l)
{
return os << l.s;
}
const std::string& get_string() const
{
return s;
}
friend bool operator<(const line_t& l, const line_t& r)
{
std::string::size_type pos = l.get_string().find_last_of('/');
std::string lhs = l.get_string().substr(pos + 1);
pos = r.get_string().find_last_of('/');
std::string rhs = r.get_string().substr(pos + 1);
return lhs < rhs;
}
};
int main()
{
std::vector<line_t> v(
std::istream_iterator<line_t>(std::cin),
std::istream_iterator<line_t>());
std::sort(v.begin(), v.end());
std::copy(v.begin(), v.end(),
std::ostream_iterator<line_t>(std::cout,"\n"));
}
> std::vector<line_t> v(
> std::istream_iterator<line_t>(std::cin),
> std::istream_iterator<line_t>());
Comeau is mistaking this statement for a function declaration. I
believe Comeau is at fault, but I would love to be corrected. You can
work around this issue with:
std::istream_iterator<line_t> in(std::cin), end;
std::vector<line_t> v(in, end);
No, Comeau is correct here. This is known as C++'s most vexing parse.
The declaration should be parsed as:
v is a function returning std::vector<line_t> and taking as
arguments
- a std::istream_iterator<line_t> named std::cin (with redundant
parentheses), and
- an unnamed pointer to a function returning
std::istream_iterator<line_t> and taking no arguments.
There are two ways to get the intended meaning of an object
declaration:
- Use named iterators as described by Jeff,or
- Add redundant parentheses around one or both of the constructor
arguments:
std::vector<line_t> v(
(std::istream_iterator<line_t>(std::cin)),
(std::istream_iterator<line_t>()));
Bart v Ingen Schenau
> Comeau is mistaking this statement for a function declaration.
> I believe Comeau is at fault, but I would love to be
> corrected.
It's an interesting question. It looks like a function
declaration. But as Comeau says, the argument in a function
declaration cannot take a qualified name, so it can't be a
(legal) function declaration. Whether this is enough to
disqualify it as a function declaration or not, however, I don't
know. (If instead of std::cin, he had written just cin, or used
the name of a local variable, there would be no doubt that it
was a function declaration.)
> You can
> work around this issue with:
>
> std::istream_iterator<line_t> in(std::cin), end;
> std::vector<line_t> v(in, end);
The more or less standard solution is to put an extra pair of
parentheses around the arguments, e.g.:
std::vector<line_t> v(
(std::istream_iterator<line_t>(std::cin)),
(std::istream_iterator<line_t>()));
(Putting them around either of the arguments is sufficient, but
there's no harm in being consistent.)
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Right; I've used the trick of fully-qualifying cin here specifically to
make the "embarrassing" parse illegal. That works with GCC, and I seem
to recall it working with at least Visual Studio 8. I guess the
question is whether the program is even well-formed.
Thanks, guys. I didn't realize I'd hit the "most vexing parse". I'm
familiar with the issue,
but for some reason, it blew right by me. Go figure.
Thanks!