C ++: what's the use of declaring a function inside another function?

Stanley Lippman "C ++ primer" mentioned on page 234 that

It is generally a bad idea to declare a function locally. However, to explain how scope interacts with overloading, we will break this practice and use local function declarations.

...
void print(const string &);
void print(double); // overloads the print function
void fooBar(int ival)
{ ...
  // bad practice: usually it a bad idea to declare functions at local scope
  void print(int); // new scope: hides previous instances of print
  print(ival); // ok: print(int) is visible
  print(3.14); // ok: calls print(int); print(double) is hidden
}

      

However, what situation might make sense to do this by declaring a function inside the function body?

I recall similar code in the schema:

(define (PowerSet set)
   (if (null? set) '(())
      (let ((PowerSetAfterHead (PowerSet (cdr set) ) ))
         (append PowerSetAfterHead
            (PowerSet (cdr set) )
            (map
               (lambda (subset)
                  (cons (car set) subset
                  )
               )
               (PowerSet (cdr set) )                                 
            )
         )
      )
   )
)

      

Is it usually hidden from misuse of a "local function" that is only meant to use an external function? something like an inner class? Or is it useful in some design patterns?

+1


source to share


2 answers


The problem arises when there is ambiguity when calling a function. Thus, to avoid ambiguity in some scope, you can update the required function, which hides all other functions with the same outer scope name.

Consider the following simple example. If you run the following program

#include <iostream>

void f( int ) { std::cout << "f( int )" << std::endl; }
void f( double ) { std::cout << "f( double )" << std::endl; }

int main() 
{
    f( 10l );

    return 0;
}

      

you will get an error like

prog.cpp: 10: 9: error: the call to the overloaded 'f (long int)' is ambiguous f (10l);



But if you add a function declaration f in main like this,

#include <iostream>

void f( int ) { std::cout << "f( int )" << std::endl; }
void f( double ) { std::cout << "f( double )" << std::endl; }

int main() 
{
    void f( double );
    f( 10l );

    return 0;
}

      

the code will be compiled and the result will look like

f( double )

      

+2


source


Your schema example declares and defines a local function.

The C ++ example just declares a local function.

These are two different things.

You can create a rough equivalent of local schema functions with lambdas in C ++ 11.

A function declaration locally simply says "there is a function of this name and signature". What's more, it does it in a narrower scope than the one outside the function, and because functions in the specified narrower scope are considered only for overloading (and not in a wider range).

No new function is created - it must be defined elsewhere. (You cannot define a local function in C ++ by disallowing things like local class and lambdas methods)



You can use this to change how the overload is resolved, but this is rarely a good idea. In case you have overloading ambiguity, you'd be better off manually converting the types and then calling the overload set and resolving it fine.

The alternative is to declare only the overload you want to call and then call it. This can lead to unexpected behavior, so only do it in a very narrow area if you can, and let us know why you are doing it and what potential problems might arise (as few programmers will have hidden overload rules placed in front of their brain when reading code without at least some clues).

I don't think I have ever encountered a situation where I had to declare a function locally.

I did this a few times because I was cracking some serious ball of dirt code and wanted to make an extremely local change for prototyping / debugging. I just declared the function signature and called it somewhere. The function was static local in another .cpp file in the same library elsewhere, I removed the static there and tested the result of calling it.

This is saved by creating a header file (or modifying it) by providing it formally including the specified header where we use it. Before I got into production, I would have gone through steps like this (and possibly cleaned up the interface of that static local function while I was at it).

So, I used it for a quick and dirty hack prototype. The last time I did this, I ended up going back to it after I did the breakout prototype, which was easier because I only touched 2 files each in 1 place.

+2


source







All Articles