cmost-vexing-parse

Purpose of function declaration within function definition


In C, one can of course declare and define functions. And this interacts with default constructor calls from C++ to yield the most vexing parse problem. Say I want to declare a function foo, define a function bar and create an instance t, I might mistakenly write this (having Python or Java in mind):

T foo();

T bar() {
    T t();
}

This will not do what I want, it will declare a function t with no arguments (or perhaps arbitrary many ones as there is no void written in there, not sure) and return type T. I would get a T instance with T t;.

Why is this syntax even allowed? What is the point of declaring a function just within a function? The linker will have to resolve this at link time anyway, and then one could just declare that function in the file scope. Is there some edge case that I am missing?


Solution

  • Not a formal explanation but just a use-case in which I would use the function-scope declaration.

    Imagine you have a C header file offering an inline static function, but in specific cases this function should rely on an internal helper function which is not part of the API.

    // file utils.h
    #ifndef UTILS_H
    #define UTILS_H
    
    // many other things...
    
    inline static
    int
    nice_util(int i,
              int j)
    {
      int k=i+2*j;
      if(i>10) // should not happen so often
      {
        void ugly_helper_function(int n); // no one else should be aware of this function
        ugly_helper_function(k);
      }
      return k;
    }
    
    #endif // UTILS_H
    

    There is probably an implementation file coming with this header-file.

    // file utils.c
    
    #include <utils.h>
    #include <stdio.h>
    
    // many other things...
    
    void
    ugly_helper_function(int n)
    {
      printf("%s(%d)\n", __func__, n);
    }
    

    Using this header-file provides the expected function but not the internal one (except if you ignore the warnings).

    // file prog.c
    #include <utils.h>
    
    int
    main(void)
    {
      // ugly_helper_function(5678); // warning: implicit declaration...
      return nice_util(12, 34);
    }
    

    Without the ability to declare the internal function at function-scope, we would have had to declare it at global-scope in the header file, and that would have made it accessible without any warning.