4

I don't understand the following problem.

class InnerBox
{
public:
    InnerBox() : mContents(123) { };
private:
    int mContents;
};


class Box
{
public:

    Box(const InnerBox& innerBox) : mInnerBox(innerBox) { };

private:
    InnerBox mInnerBox;
};


void SomeFunction(const Box& box)
{
    return;
}

int main()
{
    Box box(InnerBox());  // !!PROBLEM!! Doesn't work: compiler thinks this is a function declaration
    SomeFunction(box);    // Error, cannot convert 'function pointer type' to const Box&

    return 0;
}

The complete error message is (Visual Studio 2010)

 error C2664: 'SomeFunction' : cannot convert parameter 1 from 'Box (__cdecl *)(InnerBox (__cdecl *)(void))' to 'const Box &'

The fix is simple:

int main()
{
    InnerBox innerBox;
    Box box(innerBox);  
    SomeFunction(box);

    return 0;
 }

Is this a MSVC specific problem, and if not could someone explain what quirk of the language prevents me calling Box box(InnerBox()); ?

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
Zero
  • 11,593
  • 9
  • 52
  • 70
  • I edited the title to best reflect the problem. Pointing out the mistake in the title is less helpful to anyone else encountering it. If someone has the same problem as you, it's unlikely they know what "most vexing parse" is, so more unlikely to find this question & the answer. – Luchian Grigore Aug 15 '12 at 00:56
  • That's true. Anyway - it's now painfully obvious that this is a very common problem, but I've never come across it in about 6 years of C++ development and couldn't find an answer on the web in a couple of hours... certainly the "most vexing" problem I've encountered so far! – Zero Aug 15 '12 at 01:00

3 Answers3

5

You need to write it as:

Box box((InnerBox()));

or

Box box{InnerBox()};

This is not an MSVC specific problem. The rule in C++ is to consider any construct that could possibly be a declaration a declaration.

Without the additional parentheses, the code is declaring a function called box which returns a Box, and whose single argument is a pointer to a function taking no arguments and returning an InnerBox. (Yes -- InnerBox() actually declares a pointer to a function (not named), when used in a function parameter (this is similar to how Box[] actually declares a pointer to Box when used as a function parameter)).

Mankarse
  • 39,818
  • 11
  • 97
  • 141
  • Can you provide some detail as to why? I can't figure out why or how the compiler comes the conclusion `Box box(InnerBox());` is a function declaration. Also, is there a term for this problem, something I could have googled to find the answer? – Zero Aug 15 '12 at 00:32
5

The original like is being parsed as a function declaration (not definition) for a function named 'box' that returns a Box and takes as a parameter a function pointer that returns an InnerBox and takes no parameters InnerBox (*)(). See this for a good description of the Most Vexing Parse problem.

You can explicitly differentiate your object construction with the use of additional parentheses Box box((InnerBox()));. Or as a slightly cleaner alternative, you can use the new C++11 object construction syntax:

Box box{InnerBox()};

Rollie
  • 4,391
  • 3
  • 33
  • 55
4

Is this a MSVC specific problem, and if not could someone explain what quirk of the language prevents me calling Box box(InnerBox()); ?

To complete the other answers:

This is known as most vexing parse. It's not a problem with the compiler. It's basically a parsing specification that says that anything that can be treated as a declaration, is treated as a declaration.

In your case, you can fix it with

Box box((InnerBox()));
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625