Constructor call with temporary object

I do not 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; } 

Full error message (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 an MSVC issue, and if someone couldn’t explain that I'm sorry for the language, I forbid me to call Box box(InnerBox()); ?

+4
source share
3 answers

You need to write it as:

 Box box((InnerBox())); 

or

 Box box{InnerBox()}; 

This is not a problem with MSVC. A rule in C ++ should consider any construct that may be a declaration of a declaration.

Without additional parentheses, the code declares a function named box that returns box , and the only argument is a pointer to a function that takes no arguments and returns 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)).

+5
source

The original, as well as parsing, is like declaring a function (not a definition) for a function called "box", which returns a field and takes as a parameter a function pointer that returns an InnerBox and does not accept InnerBox (*)() parameters. See this for a good description of the problem of Vexing Parse itself.

You can explicitly distinguish the design of an object using the optional parentheses Box box((InnerBox())); . Or, as a slightly cleaner alternative, you can use the new syntax for building a C ++ 11 object:

Box box{InnerBox()};

+5
source

Is this a problem for MSVC, and if it weren’t for someone to explain that the quirk of the language forbids me to call Box box (InnerBox ());

To complete other answers:

This is called the most unpleasant parsing . This is not a compiler problem. This is basically a parsing specification that states that everything that can be considered as an ad is considered as an ad.

In your case, you can fix it with

 Box box((InnerBox())); 
+4
source

All Articles