Question

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
Was it helpful?

Solution

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++.

OTHER TIPS

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).

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.

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.

Like said in the 3rd snippet of this answer, it can help with scope shadowing.

#include <stdio.h>

void c(); // Prototype of a function named ``c''

int main() {

    c(); // call the function

    { // additional scoppe needed for C, not for C++
        int c = 0; // shadow the c function with a c integer variable
        c++;
        {
            void c(); // hide the c integer variable back with the c function
            c();
        }
        ++c;
    } //!

    return 0;
}

void c() {
    printf("Called\n");
}

I don't think this use is likely to be useful often and there are chances that it won't arise in any well designed program.

I still think this is the most likely reason for that feature, defining functions lately as for variables just doesn't sound as right.

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.

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;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top