Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

G++ takes code, Comeau barfs with "error: qualified name is not allowed"

0 views
Skip to first unread message

red floyd

unread,
Jan 27, 2009, 6:47:25 PM1/27/09
to
As far as I can tell, this code should be correct. G++ likes it, but
Comeau online hates it.

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"));

}

Jeff Schwab

unread,
Jan 27, 2009, 7:02:28 PM1/27/09
to
red floyd wrote:
> As far as I can tell, this code should be correct. G++ likes it, but
> Comeau online hates it.

> 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);

Bart van Ingen Schenau

unread,
Jan 28, 2009, 3:40:00 AM1/28/09
to

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

James Kanze

unread,
Jan 28, 2009, 8:32:47 AM1/28/09
to
On Jan 28, 1:02 am, Jeff Schwab <j...@schwabcenter.com> wrote:
> red floyd wrote:
> > As far as I can tell, this code should be correct. G++ likes it, but
> > Comeau online hates it.
> > 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.

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

Jeff Schwab

unread,
Jan 28, 2009, 10:09:34 AM1/28/09
to
James Kanze wrote:
> On Jan 28, 1:02 am, Jeff Schwab <j...@schwabcenter.com> wrote:
>> red floyd wrote:
>>> As far as I can tell, this code should be correct. G++ likes it, but
>>> Comeau online hates it.
>>> 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.
>
> 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.)

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.

red floyd

unread,
Jan 28, 2009, 11:46:30 AM1/28/09
to

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!

0 new messages