[c++] Can we have functions inside functions in C++?

I mean something like:

int main() 
{
  void a() 
  {
      // code
  }
  a();

  return 0;
}

This question is related to c++

The answer is


Starting with C++ 11 you can use proper lambdas. See the other answers for more details.


Old answer: You can, sort-of, but you have to cheat and use a dummy class:

void moo()
{
    class dummy
    {
    public:
         static void a() { printf("I'm in a!\n"); }
    };

    dummy::a();
    dummy::a();
}

No, it's not allowed. Neither C nor C++ support this feature by default, however TonyK points out (in the comments) that there are extensions to the GNU C compiler that enable this behavior in C.


Let me post a solution here for C++03 that I consider the cleanest possible.*

#define DECLARE_LAMBDA(NAME, RETURN_TYPE, FUNCTION) \
    struct { RETURN_TYPE operator () FUNCTION } NAME;

...

int main(){
  DECLARE_LAMBDA(demoLambda, void, (){ cout<<"I'm a lambda!"<<endl; });
  demoLambda();

  DECLARE_LAMBDA(plus, int, (int i, int j){
    return i+j;
  });
  cout << "plus(1,2)=" << plus(1,2) << endl;
  return 0;
}

(*) in the C++ world using macros is never considered clean.


You cannot define a free function inside another in C++.


For all intents and purposes, C++ supports this via lambdas:1

int main() {
    auto f = []() { return 42; };
    std::cout << "f() = " << f() << std::endl;
}

Here, f is a lambda object that acts as a local function in main. Captures can be specified to allow the function to access local objects.

Behind the scenes, f is a function object (i.e. an object of a type that provides an operator()). The function object type is created by the compiler based on the lambda.


1 since C++11


No.

What are you trying to do?

workaround:

int main(void)
{
  struct foo
  {
    void operator()() { int a = 1; }
  };

  foo b;
  b(); // call the operator()

}

You can't have local functions in C++. However, C++11 has lambdas. Lambdas are basically variables that work like functions.

A lambda has the type std::function (actually that's not quite true, but in most cases you can suppose it is). To use this type, you need to #include <functional>. std::function is a template, taking as template argument the return type and the argument types, with the syntax std::function<ReturnType(ArgumentTypes)>. For example, std::function<int(std::string, float)> is a lambda returning an int and taking two arguments, one std::string and one float. The most common one is std::function<void()>, which returns nothing and takes no arguments.

Once a lambda is declared, it is called just like a normal function, using the syntax lambda(arguments).

To define a lambda, use the syntax [captures](arguments){code} (there are other ways of doing it, but I won't mention them here). arguments is what arguments the lambda takes, and code is the code that should be run when the lambda is called. Usually you put [=] or [&] as captures. [=] means that you capture all variables in the scope in which the value is defined by value, which means that they will keep the value that they had when the lambda was declared. [&] means that you capture all variables in the scope by reference, which means that they will always have their current value, but if they are erased from memory the program will crash. Here are some examples:

#include <functional>
#include <iostream>

int main(){
    int x = 1;

    std::function<void()> lambda1 = [=](){
        std::cout << x << std::endl;
    };
    std::function<void()> lambda2 = [&](){
        std::cout << x << std::endl;
    };

    x = 2;
    lambda1();    //Prints 1 since that was the value of x when it was captured and x was captured by value with [=]
    lambda2();    //Prints 2 since that's the current value of x and x was captured by reference with [&]

    std::function<void()> lambda3 = [](){}, lambda4 = [](){};    //I prefer to initialize these since calling an uninitialized lambda is undefined behavior.
                                                                 //[](){} is the empty lambda.

    {
        int y = 3;    //y will be deleted from the memory at the end of this scope
        lambda3 = [=](){
            std::cout << y << endl;
        };
        lambda4 = [&](){
            std::cout << y << endl;
        };
    }

    lambda3();    //Prints 3, since that's the value y had when it was captured

    lambda4();    //Causes the program to crash, since y was captured by reference and y doesn't exist anymore.
                  //This is a bit like if you had a pointer to y which now points nowhere because y has been deleted from the memory.
                  //This is why you should be careful when capturing by reference.

    return 0;
}

You can also capture specific variables by specifying their names. Just specifying their name will capture them by value, specifying their name with a & before will capture them by reference. For example, [=, &foo] will capture all variables by value except foo which will be captured by reference, and [&, foo] will capture all variables by reference except foo which will be captured by value. You can also capture only specific variables, for example [&foo] will capture foo by reference and will capture no other variables. You can also capture no variables at all by using []. If you try to use a variable in a lambda that you didn't capture, it won't compile. Here is an example:

#include <functional>

int main(){
    int x = 4, y = 5;

    std::function<void(int)> myLambda = [y](int z){
        int xSquare = x * x;    //Compiler error because x wasn't captured
        int ySquare = y * y;    //OK because y was captured
        int zSquare = z * z;    //OK because z is an argument of the lambda
    };

    return 0;
}

You can't change the value of a variable that was captured by value inside a lambda (variables captured by value have a const type inside the lambda). To do so, you need to capture the variable by reference. Here is an exampmle:

#include <functional>

int main(){
    int x = 3, y = 5;
    std::function<void()> myLambda = [x, &y](){
        x = 2;    //Compiler error because x is captured by value and so it's of type const int inside the lambda
        y = 2;    //OK because y is captured by reference
    };
    x = 2;    //This is of course OK because we're not inside the lambda
    return 0;
}

Also, calling uninitialized lambdas is undefined behavior and will usually cause the program to crash. For example, never do this:

std::function<void()> lambda;
lambda();    //Undefined behavior because lambda is uninitialized

Examples

Here is the code for what you wanted to do in your question using lambdas:

#include <functional>    //Don't forget this, otherwise you won't be able to use the std::function type

int main(){
    std::function<void()> a = [](){
        // code
    }
    a();
    return 0;
}

Here is a more advanced example of a lambda:

#include <functional>    //For std::function
#include <iostream>      //For std::cout

int main(){
    int x = 4;
    std::function<float(int)> divideByX = [x](int y){
        return (float)y / (float)x;    //x is a captured variable, y is an argument
    }
    std::cout << divideByX(3) << std::endl;    //Prints 0.75
    return 0;
}

Local classes have already been mentioned, but here is a way to let them appear even more as local functions, using an operator() overload and an anonymous class:

int main() {
    struct {
        unsigned int operator() (unsigned int val) const {
            return val<=1 ? 1 : val*(*this)(val-1);
        }
    } fac;

    std::cout << fac(5) << '\n';
}

I don't advise on using this, it's just a funny trick (can do, but imho shouldn't).


2014 Update:

With the rise of C++11 a while back, you can now have local functions whose syntax is a little reminiscient of JavaScript:

auto fac = [] (unsigned int val) {
    return val*42;
};

But we can declare a function inside main():

int main()
{
    void a();
}

Although the syntax is correct, sometimes it can lead to the "Most vexing parse":

#include <iostream>


struct U
{
    U() : val(0) {}
    U(int val) : val(val) {}

    int val;
};

struct V
{
    V(U a, U b)
    {
        std::cout << "V(" << a.val << ", " << b.val << ");\n";
    }
    ~V()
    {
        std::cout << "~V();\n";
    }
};

int main()
{
    int five = 5;
    V v(U(five), U());
}

=> no program output.

(Only Clang warning after compilation).

C++'s most vexing parse again


All this tricks just look (more or less) as local functions, but they don't work like that. In a local function you can use local variables of it's super functions. It's kind of semi-globals. Non of these tricks can do that. The closest is the lambda trick from c++0x, but it's closure is bound in definition time, not the use time.


As others have mentioned, you can use nested functions by using the gnu language extensions in gcc. If you (or your project) sticks to the gcc toolchain, your code will be mostly portable across the different architectures targeted by the gcc compiler.

However, if there is a possible requirement that you might need to compile code with a different toolchain, then I'd stay away from such extensions.


I'd also tread with care when using nested functions. They are a beautiful solution for managing the structure of complex, yet cohesive blocks of code (the pieces of which are not meant for external/general use.) They are also very helpful in controlling namespace pollution (a very real concern with naturally complex/long classes in verbose languages.)

But like anything, they can be open to abuse.

It is sad that C/C++ does not support such features as an standard. Most pascal variants and Ada do (almost all Algol-based languages do). Same with JavaScript. Same with modern languages like Scala. Same with venerable languages like Erlang, Lisp or Python.

And just as with C/C++, unfortunately, Java (with which I earn most of my living) does not.

I mention Java here because I see several posters suggesting usage of classes and class' methods as alternatives to nested functions. And that's also the typical workaround in Java.

Short answer: No.

Doing so tend to introduce artificial, needless complexity on a class hierarchy. With all things being equal, the ideal is to have a class hierarchy (and its encompassing namespaces and scopes) representing an actual domain as simple as possible.

Nested functions help deal with "private", within-function complexity. Lacking those facilities, one should try to avoid propagating that "private" complexity out and into one's class model.

In software (and in any engineering discipline), modeling is a matter of trade-offs. Thus, in real life, there will be justified exceptions to those rules (or rather guidelines). Proceed with care, though.