4

I have these two classes:

class Foo
{
public:
      Foo() { std::cout << "in Foo constructor" << std::endl; }
};
class Bar
{
public:
    Bar() {};
    Bar(Foo foo);
private:
    Foo m_foo;
};

Bar::Bar(Foo foo) :
    m_foo(foo)
{
    std::cout << "in Bar constructor with argument Foo" << std::endl;
}

int main() {
    Bar bar(Foo()); // is something wrong here ?
    return 0;
}

I compiled and excuted it , nothing printed on screen, what did Bar bar(Foo()) do ? I have seen similarity in Do the parentheses after the type name make a difference with new? and Foo f = Foo(); // no matching function for call to 'Foo::Foo(Foo)', but I still can't figure out.

Community
  • 1
  • 1
Gary Gauh
  • 4,984
  • 5
  • 30
  • 43
  • 1
    Most vexing parse indeed. Take a look at http://en.wikipedia.org/wiki/Most_vexing_parse ! – Nbr44 Apr 05 '13 at 04:13

2 Answers2

1

To achieve the same without changing the semantics (ie. not using the copy or assignment constructor), add parentheses to disambiguate the syntax (the compiler does not know if you declare a function locally or if you build an object, by default the former is prioritized by the C++ standard):

int main() {
    Bar bar ( (Foo()) );
    return 0;
}

As pointed out in the Wikipedia page that was posted in the comments, it is an issue with the C++ grammar itself, not much you can do about it.

Community
  • 1
  • 1
Qortex
  • 7,087
  • 3
  • 42
  • 59
0

OK it has been pointed out that compiler thinks that you are declaring a function. By Pubby and Nbr44. This is a way how to get around it. Just let the compiler know that you are declaring variable.

int main() {
    Bar bar = Foo();
    return 0;
}
Community
  • 1
  • 1
Kupto
  • 2,802
  • 2
  • 13
  • 16
  • Just `Bar bar = Foo();` is sufficient. – jxh Apr 05 '13 at 04:29
  • Warning, the semantics is not the same, you'll end up calling the assignment operator here. See [this SO post](http://stackoverflow.com/questions/2462773/c-copy-construct-construct-and-assign-question) for example. – Qortex Apr 05 '13 at 04:30
  • right, did not realize that. Edited... – Kupto Apr 05 '13 at 04:32
  • @Mic: The answer in the post you indicated specifically says it is not assignment. – jxh Apr 05 '13 at 04:50
  • @Kupto: No, it wasn't, it involved a copy constructor in addition to the `Foo` constructor. Your fix only involves the `Foo` constructor. You never had assignment. – jxh Apr 05 '13 at 04:57
  • now I am lost... what did you mean by `The answer in the post you indicated specifically says it is not assignment.`? – Kupto Apr 05 '13 at 05:04
  • @Kupto: http://stackoverflow.com/a/2462819/315052 – jxh Apr 05 '13 at 05:07
  • Admittedly I'm treading in self-proclaimed naivety, but won't this potentially introduce copy elision? I.e. construct a temp Bar initialized with Foo(), then fire the copy constructor for Bar to pull over the data, then the destructor of the temp? I realize most compilers optimize this, but they also tend to require the copy-ctor be available at compile-time even when its not used after optimization (or so I recall, anyway, perhaps wrongly). – WhozCraig Apr 05 '13 at 05:12
  • @WhozCraig: You are correct, in the `Bar bar = Bar(Foo());` formulation, the copy constructor can be optimized away. – jxh Apr 05 '13 at 05:21
  • Absolutely, my bad. The copy constructor would be called and not the assignment operator (which would be called, but only in a statement separate from the construction). – Qortex Apr 05 '13 at 05:36