81

I'm certainly missing something, but I do not understand why this compiles (with both g++ & clang++):

struct A
{
};
struct B
{
};

int main()
{
  A a(B);
}

First of all, B is a type... not a value. How should I interpret this code?

Picaud Vincent
  • 10,518
  • 5
  • 31
  • 70
  • 38
    This is known as the [Most Vexing Parse](https://en.wikipedia.org/wiki/Most_vexing_parse) – alter_igel Dec 03 '19 at 17:43
  • 8
    @alterigel Is it really? In this case there is no ambiguity. It can only be a function declaration. It is not `A a(B());` which could be a variable definition or function declaration. – walnut Dec 03 '19 at 17:51
  • 8
    You'd be surprise to know that `struct A{}; int main() { A(foo); }` [compiles as is](https://gcc.godbolt.org/z/g2hYsz), even if `foo` doesn't name anything. – Aykhan Hagverdili Dec 03 '19 at 17:56
  • Does this answer your question? [Most vexing parse confusion](https://stackoverflow.com/questions/17060725/most-vexing-parse-confusion) – Mansoor Dec 03 '19 at 18:01
  • 20
    @alterigel -- this is **not** the most vexing parse. Look at the examples on the page that you linked to. This is simply a function declaration. – Pete Becker Dec 03 '19 at 18:27
  • 3
    @PeteBecker, it might be better to explain _why_ this isn't MVP instead of just asserting that it is not, which I believe walnut already did above. – JPhi1618 Dec 04 '19 at 19:02
  • Does this answer your question? [Default constructor with empty brackets](https://stackoverflow.com/questions/180172/default-constructor-with-empty-brackets) – Islam Hassan Dec 06 '19 at 13:31
  • @IslamEl-Rougy, yes using {} for constructors avoid this. I have no problem with the answers I got... although this was certainly my _most vexing "question"_ :-) – Picaud Vincent Dec 06 '19 at 13:57

3 Answers3

87

It's interpreted as the declaration of a function named a, which takes one argument of type B and returns A.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • 5
    And that is why it is Most and Vexing. A solution: (not that it actually solves anything since it exposes the bad construction) `A a{B};` – user4581301 Dec 03 '19 at 17:46
  • 23
    @user4581301 -- it's **not** the most vexing parse. It's simply a function declaration. – Pete Becker Dec 03 '19 at 18:27
  • Right. Most vexing parse has more meat in the accidental function call. – user4581301 Dec 03 '19 at 18:44
  • 11
    The weirdest part about it is that C++ does not allow nested functions, but _does_ allow declarations inside a function. – The_Sympathizer Dec 04 '19 at 12:07
  • 2
    @The_Sympathizer just like everything else in C++, it has its valid use cases. – Aykhan Hagverdili Dec 04 '19 at 17:22
  • 6
    Sounds like a good motivation for adding support for nested functions to C++; not only would they be useful, they'd turn this odd wart into a reasonable design :) – Jeremy Friesner Dec 04 '19 at 18:11
  • @JeremyFriesner But we couldn't change the meaning of local function declarations as it is currently, because that would break existing code. That makes the case for nested function definitions somewhat less compelling. Particularly since we can use lambdas now. – Brian Bi Dec 04 '19 at 23:33
  • 1
    @Brian My proposed change would be allowing inline-code of the form `void Foo() { void Bar() {printf("Bar!\n");} printf("Foo!\n"); }` ... which wouldn't break compatibility simply because code of that form already doesn't compile, and therefore no code like that exists to be broken. Not that I'm willing to actually try to get that into the language, rather I'm just daydreaming :) – Jeremy Friesner Dec 05 '19 at 00:04
  • @JeremyFriesner Yeah, but it's a little bit counterintuitive that a nested *declaration* would declare the function at namespace scope whereas a nested *definition* would create a local function. How do you forward-declare a local function, then? – Brian Bi Dec 05 '19 at 01:31
  • 3
    @Brian "a little bit counterintuitive" could be C++'s motto :). As for forward declarations, I would just deem them Not Supported for local functions, and call it done. – Jeremy Friesner Dec 05 '19 at 01:35
15

It's simply a function declaration declaring a to be a function returning A and taking one unnamed parameter of type B.

It is valid because function declarations as opposed to function definitions are allowed within function definitions.

machine_1
  • 4,266
  • 2
  • 21
  • 42
13

This issue is known as the most vexing parse. The line A a(B); can be interpreted as the declaration of a function named a returning an object of type A and taking an unnamed parameter of type B.

One way to avoid this issue is to use the uniform initialization syntax which was introduced in C++11, which consists in using braces instead of parenthesis: A a{B}; returns an error. The line is now interpreted as a variable declaration initialized with B, which is a type instead of a value.

Here's more information:

The Most Vexing Parse: How to Spot It and Fix It Quickly

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
Guilmo
  • 230
  • 1
  • 7
  • 12
    I don't think this should be called "*most vexing parse*". It is just a usual function declaration as it also exists in C. There is no ambiguity resolution necessary because the line can only be a function declaration, nothing else. Look at your link. The examples are all different from this. – walnut Dec 03 '19 at 19:07
  • 3
    While that's true, it is related to the most vexing parse. It's just that this also included a typo where a type name was used alone instead of a variable or a constructor call, as was probably the original intent. – Miral Dec 04 '19 at 03:36
  • 1
    Yeah, "Most Vexing Parse" is an useful answer in this case, even though the actual case in the question is just "Slightly Vexing Parse". – jpa Dec 04 '19 at 19:45
  • 1
    @wlanut: The empty structures `struct A { };` are not valid in standard C, even if some compilers allow them. Drop the braces and there wouldn't be a problem there. Also, in C, declaring or defining `struct A` does not create a type name `A` (you must prefix it with `struct`, or add `typedef struct A A;` somewhere before `A` is used without the `struct` prefix). Also in C, there is no alternative parse to the function declaration — using `type name(...);` simply cannot ever be a variable definition; it is always a function declaration (or invalid). The code in the question is not valid in C. – Jonathan Leffler Dec 10 '19 at 22:25
  • @jpa, I can't find anything written about "Slightly Vexing Parse" anywhere. Is this name just oral tradition? I'd like to read more about it. – Keith Russell Oct 16 '20 at 21:21
  • @KeithRussell It was just a play on words. This question is a simpler case that is related to the well known "Most Vexing Parse". That's why I referred to this question as "Slightly Vexing Parse". – jpa Oct 17 '20 at 08:58