0

In Visual Studio, if I write:

Foo f();
f.doSomething();

doSomething() isn't recognized by the IDE.

However if I write:

Foo f = Foo();
f.doSomething();

Visual Studio recognizes this object as it should. Referring to the C++ Standard, the first method should be perfectly fine, shouldn't it?

Zong
  • 6,160
  • 5
  • 32
  • 46
user3067395
  • 560
  • 6
  • 17
  • no, the first one is a function declaration. – yngccc Dec 06 '13 at 18:14
  • 2
    Try either `Foo f;` or `Foo f{};` – woolstar Dec 06 '13 at 18:15
  • 4
    This is a quirk of C++. http://stackoverflow.com/questions/1424510/most-vexing-parse-why-doesnt-a-a-work – ApplePie Dec 06 '13 at 18:16
  • @AlexandreP.Levasseur That question is about the most vexing parse. This is a similar issue, but it is **not** the MVP. –  Dec 06 '13 at 18:48
  • @H2CO3 As I stated below, it actually **is** a form of MVP. Meyers uses this exact situation as an example of it in "Effective STL" when discussing it. – Zac Howland Dec 07 '13 at 03:16
  • @ZacHowland It sometimes is called "a vexing parse", however the MVP is **not** this example. –  Dec 07 '13 at 06:35
  • @H2CO3 "Effective STL", Item 6 is all about MVP. At the top of page 35 (in the 3rd edition), he uses `Widget w();` as an example of it. He also goes on to use a more complicated example `list data(istream_iterator(dataFile), istream_iterator());`, but the difference between the two is simply semantics. They are the result of the same parsing rules (namely, if it can be parsed as a function declaration, it will be). – Zac Howland Dec 07 '13 at 07:14

2 Answers2

4

The statement Foo f(); is a function declaration, not a declaration of a local variable f of type Foo. To declare a local Foo value using the parameterless constructor you must omit the ()

Foo f;
f.doSomething();
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • How do I call a constructor with parameters then? Especially when I declare them as member functions and want to initialize them in the constructor of the class. This would lead to a double initialization, right? First one at `Foo f;` and the second one at `f = Foo(int param);` – user3067395 Dec 06 '13 at 18:26
  • 1
    if you don't have parameters inside the constructor, don't use parentheses. Otherwise use the parentheses with the arguments in them. – Gasim Dec 06 '13 at 18:28
  • @user3067395 `f = Foo(int param);` is not how you construct an object (that's another function declaration). Surely you meant `f = Foo(param);`? –  Dec 06 '13 at 18:47
1
Foo f();

This is a form of what is known as the Most Vexing Parse. If you are instantiating an automatic variable with its default constructor, there is no need to have the ().

Foo f;

If you need to call a different constructor, use the ():

Foo f(some other data);

Or the newer initialization syntax (C++11):

Foo f { some other data };

Details

Scott Meyers talks about this in Item 6 of "Effective STL". The basic rule for C++ is that if a line can be parsed as a function declaration, it will be. This means that both of the following lines are parsed as function declarations, not variable instantiations:

Foo f(); // declares a function f that takes no parameters and returns a Foo
list<int>  data(istream_iterator<int>(dataFile), istream_iterator<int>()); // declares a function that takes 2 istream_iterators and returns a list<int>
Zac Howland
  • 15,777
  • 1
  • 26
  • 42
  • 1
    This is **not** the most vexing parse. It's simply a function declaration. The page that you linked to gives several examples of the most vexing parse, and this is **not** one of them. – Pete Becker Dec 06 '13 at 18:47
  • 1
    @PeteBecker Incorrect. It **is** a form of MVP: http://stackoverflow.com/questions/1424510/most-vexing-parse-why-doesnt-a-a-work, http://arstechnica.com/civis/viewtopic.php?f=20&t=767929, http://herbsutter.com/2013/05/09/gotw-1-solution/, etc. – Zac Howland Dec 06 '13 at 18:58
  • 1
    `int f();` is a function declaration, and has been since C. There's nothing vexing about it. If you **read** the page that you originally linked to, you'll see that the "most vexing parse" is much more complex, and the result is not just unexpected, but not the least bit useful. – Pete Becker Dec 06 '13 at 19:24
  • If you read Herb's GOTW link above, you'll see that his introduction to the most vexing parse is `widget w();`, which is basically the same thing we have here. – Zac Howland Dec 06 '13 at 19:28
  • 1
    Yes, if Herb said it, it must be the absolute, indisputable truth. He never oversimplifies anything. – Pete Becker Dec 06 '13 at 19:29
  • And the difference between `Foo f(int i);` and `Foo f();` is what (in terms of MVP)? – Zac Howland Dec 06 '13 at 19:56
  • To be clear, Scott Meyers (who coined the phase) describes it in Item 6 of Effective C++ (2nd Edition) as a line you intend to declare a variable, but is actually going to declare a function (and thus, will do nothing). The fact that you have or do not have parameters in a constructor you are intending to call is irrelevant. – Zac Howland Dec 06 '13 at 20:09
  • 1
    How is it "vexing" to have to write `int f;` to define an object and `int f();` to define a function? Yes, the "most vexing parse" comes out of the rule that makes `int f();` a function declaration (which **does something**), but that doesn't make it **vexing**. Nor does the fact that beginners get it wrong; once it's explained they have no problem with it, unlike the confusing parsing examples on the Wikipedia page that you first cited. – Pete Becker Dec 06 '13 at 21:21
  • You can take it up with the author of the book ... who is credited for coining the phrase. "Effective STL", Item 6. One of the examples he gives is `Widget w(); // uh oh ...`. So you can state that it isn't an example of MVP all you want; the guy who is credited with coining the phrase disagrees with you. – Zac Howland Dec 07 '13 at 03:14
  • You're quoting out of context. That example comes deep in the discussion of the most vexing parse, and it's prefaced by "[The most vexing parse is] consistent with a universal rule in C++ ...". That is, it's an example of something that comes from the general rule, not of the most vexing parse. Which is why he refers to it as a "faux pas". – Pete Becker Dec 07 '13 at 11:33
  • "But it's consistent with a universal rule in C++, which says that pretty much anything that can be parsed as a function declaration will be. If you have been programming in C++ for a while, you've almost certainly encountered **another manifestation** of this rule. How many times have you seen this mistake? `class Widget { ... }; Widget w();`" That is to say, the same rule that causes `list data(istream_iterator(dataFile), istream_iterator());` to be parsed as a function causes `Widget w();` to be so as well. Both of these are *faux pas*, not just the latter. – Zac Howland Dec 07 '13 at 20:29