views:

804

answers:

6

Most C++ programmers like me have made the following mistake at some point:

class C { /*...*/ };

int main() {
  C c();     // declares a function c taking no arguments returning a C,
             // not, as intended by most, an object c of type C initialized
             // using the default constructor.
  c.foo();   // compiler complains here.

  //...
}

Now while the error is pretty obvious once you know it I was wondering if there is any sensible use for this kind of local function declaration except that you can do it -- especially since there is no way to define such a local function in the same block; you have to define it elsewhere.

I think that Java-style local classes are a pretty nice feature which I tend to use often, especially the anonymous sort. Even local C++ classes (which can have inline-defined member functions) have some use. But this local function declaration without definition thing seems very awkward to me. Is it just a C-legacy or is there some deeper use case which I am not aware of?

Edit for the non-believers: C c() is not a function pointer declaration.

This program

int main()
{
  void g();
  cout << "Hello ";
  g();
  return 0;
}

void g()
{
  cout << "world." << endl;
}

outputs Hello world. This program

void fun()
{
  cout << "world." << endl;
}

int main()
{
  void g();
  g = fun;
  cout << "Hello ";
  g();
  return 0;
}

does not compile. gcc complains:

error: cannot convert 'void ()()' to 'void ()()' in assignment

comeau:

error: expression must be a modifiable lvalue
+1  A: 

It's a forward declaration prototype. Conceivably if you have a lot of local functions, or local functions which call one another contrary to order of definition, you may need it.

chaos
I don't understand your point here: In your usecase, I would just declare all functions at the beginning of the source-file (or even in some private header) and then happily implement away. Why would I ever want/need to _declare_ one funciton inside another function?
Tobias
+2  A: 

The only use I can think of is to reduce the scope of function declarations:

int main()
{
    void doSomething();
    doSomething();
    return 0;
}

void otherFunc()
{
    doSomething();  // ERROR, doSomething() not in scope
}

void doSomething()
{
    ...
}

Of course, there are much better solutions to this. If you need to hide a function, you should really restructure your code by moving functions into separate modules so that the functions which need to call the function you want to hide are all in the same module. Then, you can make that function module-local by declaring it static (the C way) or by putting it inside an anonymous namespace (the C++ way).

Adam Rosenfield
A: 

The only sane use for it I can see is to allow only one function in a compilation unit to know about a function defined in another compilation unit. I think that would be a somewhat reasonable use, but that's the only one I can think of, and I think that's overkill.

Rob K
But why would you declare a function inside the definition of another one (as opposed to outside the function definition or in a header)?
Tobias
Like I said, so that only that function could see it.
Rob K
A: 

If you want to differ between declaring a function taking no parameters and instantiating a class with default destructor, skip the parenthesis.

class C
{
  public:
    void foo() {}
};


int main()
{
    // declare function d, taking no arguments, returning fresh C
    C d();

    // instantiate class (leave parenthesis out)
    C c;
    c.foo();

    // call declared function
    C goo = d();

    return 0;
}

C d()
{
    C c;
    // ..
    return c;
}
Magnus Skog
My question is not how to instantiate an object, my question is, why would you ever declare the function d the way you did it (as opposed to declaring it outside of main)?
Tobias
A: 

I sometimes do it for the same reason we are encouraged to declare variables right before their first use (and not earlier), namely, to improve readability. (Yes, I realize that for variables it is more important because it relieves you of the need to check whether the variable is used before what you think is its first use). Having the prototype (especially if it's more involved than just c()) close to the function invocation improves readability. The fact that the special case C c() is misleading to humans is unfortunate, but the general idea of declaring functions locally has merit.

Of course, this is true also for function names that are already in scope. Why not redeclare every function before its every use? My answer to that: do all things in moderation. Too much clutter impedes readability (as well as maintainability --- should the function's signature ever change). So while I wouldn't make a rule out of it, it is sometimes useful to declare functions locally.

Ari
Have you ever done it? Do you know someone who has ever done this? I don't, and it would be great if you could link to some _real_world example. This would be really interesting.
Tobias
I have a vague recollection of actually doing it once or twice, but I don't remember a specific instance. The thing is that most functions I call are class methods, so it is pretty rare.
Ari
+1  A: 

I've wanted local function declarations in C when I wanted to pass them as arguments to some other function. I do this all the time in other languages. The reason is to encapsulate the implementation of data structures.

E.g. I define some data structure, e.g. a tree or a graph, and I don't want to expose the details of its internal implementation, e.g. because I may want to change or vary it. So I expose accessor and mutator functions for its elements, and a traversal function to iterate over the elements. The traversal function has as its argument a function that operates on an element; the traversal function's task is to execute the argument function on each element and possibly aggregate the results in some way. Now when I call the traversal function, the argument function is usually some specialized operation that depends on local state and therefore should be defined as a local function. Having to push the function, with the variables that contain the local state, outside to be global, or into an inner class created specifically to hold them, is butt ugly. But this is a problem I have with C and Java, not with C++.

reinierpost
OK, so you are saying it is a C legacy, which lost its purpose in C++?
Tobias
Not exactly. I am not actually experienced enough in C++ -- with or without templates -- to be able to tell how I would typically address this situation. Iterators are common in C++, but about traversal methods that take functions as arguments I'm not so sure.
reinierpost
Update: see http://stackoverflow.com/questions/2116128/easier-way-to-do-callbacks-for-vectors-or-maybe-something-else-in-the-stl-c
reinierpost
Sample code would be nice :) Eg, here is what I'd have to do if local function declarations were illegal, here it is using the local declaration.
Jon