views:

154

answers:

3

I had this problem happen to me in the past http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.19

My question is, when writing

Foo x(Bar());

Why is it "declaring a non-member function that returns a Bar object" ? i can understand it if i wrote

Foo x(Bar);

But what does it think the () means in Bar()?

+5  A: 

Bar() there means "a function that takes no arguments and returns Bar". Consider a declaration of such a function:

Bar GetBar();

if you remove the name of the function from this, what remains will describe the function type. Some examples of where it's used is in template arguments; e.g. you can write this:

std::function<int(float)> f1;
std::function<Bar()> f2;

Hopefully this explains the syntax in general. Now what this means in this particular case. When a function type is used as a type of function argument, it is automatically subsituted for a function pointer type. So the equivalent (but clearer) declaration would be:

Foo x(Bar(*)());
Pavel Minaev
ah i understand. i always thought you MUST write Bar(*)()
acidzombie24
"for a type of variable": Can you please clarify what you mean with that? This equivalence is only true for a function parameter.
Johannes Schaub - litb
Good point, I've fixed this.
Pavel Minaev
+3  A: 

Consider the following more simple example:

void fn1(int a)
{
}

fn1 is a function that takes a single int paramter.

Now take a look at fn2:

//Same as typing void fn2(int (*b)()) 
void fn2(int b())
{
}

Here fn2 does not take in an int, but it takes in a function that returns an int.

Now if you wanted to declare fn1 you could type it like so:

void fn1(int);//ommit the parameter name

And you can also declare fn2 like so:

void fn2(int());

Example usage:

#include <iostream>

int a()
{
  sd::cout<<"hi"<<std::endl;
  return 0;
}

void fn2(int b())
{
  b();
}

int main(int argc, char **argv)
{
  fn1(3);
  fn2(a);
}

Output will be:

hi

Now there is one more topic to understand... You can forward declare functions with scope.

a.cpp:

void a()
{
  void c();
  c();
}

//void b()
//{
//   c();//<--- undeclared identifier
//}

int main(int argc, char**argv)
{
   a();
   return 0;
}

c.cpp

#include <iostream>

void c()
{
   std::cout<<"called me"<<std::endl;
}

g++ a.cpp c.cpp ./a.out

Output will be:

Called me

And tying it all together. If you do this:

int main(int argc, char**argv)
{
  int b();

  return 0;
}

You are forward declaring a function called b() that returns type int and takes no parameters

If you would have done b = 3; then you'd get a compiling error as you can't assign a value to a forward declared function.

And once you've read all that it becomes clear:

Foo x(Bar());

You are forward declaring a function x that returns a type Foo and takes in a parameter to a function that returns a type Bar.

Brian R. Bondy
From what i understood i must always write void fn2(int (*b)())
acidzombie24
It is the same as typing fn2(int (*b)())
Brian R. Bondy
A: 

Unfortunately it doesn't seem to be online, but Scott Meyers' book, Effective STL, has a good, detailed explanation of what's going on in your example in Item 6: Be alert for C++'s most vexing parse.

On the plus side, the book is worth the price for anyone serious about C++.

Michael Burr