4

The next few lines I'm going to write come from the book "The C++ Standard Library - A tutorial and reference".

Initialize by using standard input:

//read all integer elements of the deque from standard input
std::deque<int> c((std::istream_iterator<int>(std::cin)),
(std::istream_iterator<int>()));

Don't forget the extra parentheses around the initializer arguments here. Otherwise, this expression does something very different and you probably will get some strange warnings or errors in following statements. Consider writing the statement without extra parentheses:

std::deque<int> c(std::istream_iterator<int>(std::cin),
std::istream_iterator<int>());

In this case, c declares a function with a return type that is deque. Its first parameter is of type istream_iterator with the name cin, and its second unnamed parameter is of type "function taking no arguments returning istream_iterator." This construct is valid syntactically as either a declaration or an expression. So, according to language rules, it is treated as a declaration. The extra parentheses force the initializer not to match the syntax of a declaration.

I can see why the one with extra parentheses is not considered a function declaration, but I can't see what would make the one without into a function declaration though? For it has parentheses around (std::cin), and as far as I know variables may not have names with parentheses?

Am I missing something?

xcrypt
  • 3,276
  • 5
  • 39
  • 63
  • possible duplicate of [Most vexing parse: why doesn't A a(()); work?](http://stackoverflow.com/questions/1424510/most-vexing-parse-why-doesnt-a-a-work) – pmr Jan 17 '12 at 23:22

3 Answers3

5

The tutorial you read is wrong. This:

std::deque<int> c(std::istream_iterator<int>(std::cin), std::istream_iterator<int>());

Can't be parsed as a function declaration because std::cin can't be a name of a parameter. If you remove the std qualifier though:

std::deque<int> c(std::istream_iterator<int>(cin), std::istream_iterator<int>());

then you get a function declaration.

[...] and as far as I know variables may not have names with parentheses?

The parentheses aren't part of the name. You can just put them there, how many you like:

int ((((((a)))))) = 12345; // valid code!
a++; // the variable is named 'a'
Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
  • On GCC, `std::deque c(std::istream_iterator(std::cin), std::istream_iterator());` seems to compile fine, but testing it on the online Comeau compiler gives me an error, which leads me to believe you need the extra parenthesis (I want to test it on MSVC, but I dont have access at the moment). – Jesse Good Jan 18 '12 at 00:06
  • Yes I also believe this has something to do with how the compiler actually implements it, because after reading the linked question, many statements there will not give any errors on MSVC – xcrypt Jan 18 '12 at 00:15
  • @Jesse: Hmm, VS2005 says `error C2751: 'std::cin' : the name of a function parameter cannot be qualified`. Congratulation, we found a bug in at least one compiler. We just have to know which. I'll dig further later. :) – Yakov Galka Jan 18 '12 at 00:19
  • @ybungalobill: I believe GCC is wrong, see [this question](http://stackoverflow.com/questions/4417219/use-of-qualified-name-in-function-parameter), and proper syntax would be to add parenthesis around `std::istream_iterator()`. – Jesse Good Jan 18 '12 at 01:28
  • @Jesse: I'm not sure either way. The only relevant part of the standard is "Just as for the ambiguities mentioned in 6.8, the resolution is to consider any construct that could possibly be a declaration a declaration." [dcl.ambig.res] Unfortunately it's vague. If the declarator has a qualified-id, does it mean that it can't possible be a declaration? In other words, what the standard doesn't say is which should be done first: 1) object vs function declaration disambiguation 2) verification of the rule from [dcl.meaning]. – Yakov Galka Jan 18 '12 at 07:32
3

If a statement can be parsed as either a function prototype or a variable declaration with a constructor argument, the function prototype takes precedence. This is opposite of most people's expectations, and thus it is named the Most Vexing Parse.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
1

as far as I know variables may not have names with parentheses

That's the assumption that's wrong; the parentheses aren't part of the variable name, they're just ignored (in this context).

From the C++ standard ([dcl.decl]):

declarator:

  • ptr-declarator
  • noptr-declarator parameters-and-qualifiers trailing-return-type

ptr-declarator:

  • noptr-declarator
  • ptr-operator ptr-declarator

noptr-declarator:

  • declarator-id attribute-specifieropt
  • noptr-declarator parameters-and-qualifiers
  • noptr-declarator [ constant-expressionopt ] attribute-specifieropt
  • ( ptr-declarator )

and ([dcl.fct]):

parameter-declaration-clause:

  • parameter-declaration-listopt ...opt
  • parameter-declaration-list , ...

parameter-declaration-list:

  • parameter-declaration
  • parameter-declaration-list , parameter-declaration

parameter-declaration:

  • attribute-specifieropt decl-specifier-seq declarator
  • attribute-specifieropt decl-specifier-seq declarator = assignment-expression
  • attribute-specifieropt decl-specifier-seq abstract-declaratoropt
  • attribute-specifieropt decl-specifier-seq abstract-declaratoropt = assignment-expression

Hopefully you can follow these grammar definitions to see that parentheses are indeed allowed, but if not, just ask and I'll try to clarify.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680