356

I mean something like:

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

  return 0;
}
jww
  • 97,681
  • 90
  • 411
  • 885
Rella
  • 65,003
  • 109
  • 363
  • 636
  • 2
    Why are you trying to do this? Explaining your purpose might allow someone to tell you the right way to achieve your goal. – Thomas Owens Dec 01 '10 at 13:26
  • 8
    gcc supports [nested functions](http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_5.html#SEC71) as a non-standard extension. But better don't use it even if you are using gcc. And in C++ mode, it is not available anyway. – Sven Marnach Dec 01 '10 at 13:32
  • 64
    @Thomas: Because it would be good to reduce the scope of a? Functions in functions is a usual feature in other languages. – Johan Kotlinski Dec 01 '10 at 13:32
  • 2
    @kotlinski: The C++ way of doing this would be using classes or namesapces. – Sven Marnach Dec 01 '10 at 13:34
  • 95
    He's talking about nested functions. Similarly to being able to next classes inside classes, he wants to nest a function inside a function. Actually, I've had situations where I would have done so, too, if it were possible. There are languages (e.g. F#) which allows this, and I can tell you that it can make code much more clearer, readable and maintainable without polluting a library with dozens of helpers functions that are useless outside of a very specific context. ;) – Mephane Dec 01 '10 at 13:35
  • 36
    @Thomas - nested functions can be an excellent mechanism for breaking complex functions/algorithms *without* without filling the current scope with functions that are *not* of general use within the enclosing scope. Pascal and Ada have (IMO) lovely support for them. Same with Scala and many other old/new respected languages. Like any other feature, they can also be abused, but that's a function of the developer. IMO, they have been far more beneficial that detrimental. – luis.espinal Dec 01 '10 at 17:22
  • @Kambubus - gcc has support for nested functions, but it is not a standard. C++0x has support for lambdas. They can be used *instead of* nested functions, but I wouldn't do so. Lambdas are for parametrization/composition of algorithms whereas nested functions are (when used correctly) for implementing manageable structures within complex code blocks. – luis.espinal Dec 01 '10 at 17:25
  • As you now know the answer is no. This is, if I recall correctly, why C/C++ and their relatives are not "block structured languages". – David Heffernan Dec 05 '10 at 19:09
  • http://meta.stackoverflow.com/questions/319747/editing-potential-answers-into-questions I made this question to conform to the guidelines there – Johannes Schaub - litb Apr 13 '16 at 13:32
  • 1
    Possible duplicate of [is it possible in C or C++ to create a function inside another?](http://stackoverflow.com/questions/2256647/is-it-possible-in-c-or-c-to-create-a-function-inside-another) – Anderson Green Sep 08 '16 at 04:32

13 Answers13

463

Modern C++ - Yes with lambdas!

In current versions of c++ (C++11, C++14, and C++17), you can have functions inside functions in the form of a lambda:

int main() {
    // This declares a lambda, which can be called just like a function
    auto print_message = [](std::string message) 
    { 
        std::cout << message << "\n"; 
    };

    // Prints "Hello!" 10 times
    for(int i = 0; i < 10; i++) {
        print_message("Hello!"); 
    }
}

Lambdas can also modify local variables through **capture-by-reference*. With capture-by-reference, the lambda has access to all local variables declared in the lambda's scope. It can modify and change them normally.

int main() {
    int i = 0;
    // Captures i by reference; increments it by one
    auto addOne = [&] () {
        i++; 
    };

    while(i < 10) {
        addOne(); //Add 1 to i
        std::cout << i << "\n";
    }
}

C++98 and C++03 - Not directly, but yes with static functions inside local classes

C++ doesn't support that directly.

That said, you can have local classes, and they can have functions (non-static or static), so you can get this to some extend, albeit it's a bit of a kludge:

int main() // it's int, dammit!
{
  struct X { // struct's as good as class
    static void a()
    {
    }
  };

  X::a();

  return 0;
}

However, I'd question the praxis. Everyone knows (well, now that you do, anyway :)) C++ doesn't support local functions, so they are used to not having them. They are not used, however, to that kludge. I would spend quite a while on this code to make sure it's really only there to allow local functions. Not good.

Alecto Irene Perez
  • 10,321
  • 23
  • 46
sbi
  • 219,715
  • 46
  • 258
  • 445
  • 3
    Main also takes two args if you're going to be pedantic about the return type. :) (Or is that optional but not the return these days? I can't keep up.) – Leo Davidson Dec 01 '10 at 13:29
  • 3
    This is just bad - it breaks every convention of good, clean code. I can't think of a single instance where this is a good idea. – Thomas Owens Dec 01 '10 at 13:29
  • 37
    @Thomas Owens: It's good if you need a callback function and don't want to pollute some other namespace with it. – Leo Davidson Dec 01 '10 at 13:31
  • @Leo: That callback is a good argument pro. See Konrad's answer for how to do it in C++1x. – sbi Dec 01 '10 at 13:33
  • 12
    @Leo: The standard says there are two permissible forms for main: `int main()` and `int main(int argc, char* argv[])` – John Dibling Dec 01 '10 at 13:33
  • @John: What about `int main(int argc)`? I thought that was Ok, too? – sbi Dec 01 '10 at 13:35
  • 1
    @Thomas Owens: Actually, the idea isn't bad. It's just that the code required to achieve the goal smells 'hack'. ;) – Mephane Dec 01 '10 at 13:37
  • 12
    The standard says `int main()` and `int main(int argc, char* argv[])` must be supported and others may be supported but they all have return int. – JoeG Dec 01 '10 at 13:37
  • 3
    It's useful in template definitions - they have to go in a header file, so using a local function is the only way to avoid namespace pollution. – JoeG Dec 01 '10 at 13:39
  • @sbi: Not according to the standard. implementations can provide their own versions, but the only 2 required by the std are `int main()` and `int main(int argc, char* argv[])` – John Dibling Dec 01 '10 at 13:54
  • No agree on "C (and, thus, C++) doesn't have local functions". By that argumentation, C++ must not even exist, because everything that C does not have wouldn't be had by C++, too (I think that was one of the most crazy phrases I've ever written down). – Sebastian Mach Dec 01 '10 at 14:33
  • @phresnel: That's indeed a very valid objection. Thanks for pointing it out. I fixed this. – sbi Dec 01 '10 at 14:43
  • my next question is - how to get rid of having to write X::? – Rella Dec 02 '10 at 11:28
  • 2
    @Kabumbus: You can't. That's why it is called a _workaround_. If the syntax were smooth, it'd be called a _solution_ to your problem instead. – sbi Dec 03 '10 at 08:45
  • @sbi: yes you can, see some of the other solutions, e.g. @phresnel’s. Just overload `operator ()`. – Konrad Rudolph Dec 05 '10 at 19:45
  • @Konrad: Yep, I saw this now. It's indeed clever, but I think that I would shudder if I ran into such code. So much syntactical noise for so little signal. – sbi Dec 05 '10 at 20:08
  • @LeoDavidson Actually `main()` can take [3 arguments](http://stackoverflow.com/questions/10321435/is-char-envp-as-a-third-argument-to-main-portable) the last one being for the environment variables - `int main(int argc, char *argv[], char *envp[])`. ;)))) – rbaleksandar Oct 06 '16 at 10:53
  • @rbaleksandar: You might want to follow the link you provided and actually read the answers there. (Please do not forget to pull your foot out of your mouth once you're done.) – sbi Oct 06 '16 at 11:10
  • @sbi I don't get it. Beside the fact that it's a Unix thing (though not across all flavours) it is a perfectly valid parameter (one should go for [`getenv`](http://en.cppreference.com/w/cpp/utility/program/getenv) though). – rbaleksandar Oct 06 '16 at 11:21
  • @rbaleksandar: If you want to get it, you might want to follow the link you provided and actually read the answers there. – sbi Oct 06 '16 at 12:38
  • To improve understandability, the struct may have some better name, like Helpers, and probably a comment, which states the intention. This does not avoid excessive typing, though. – Alex Che May 19 '17 at 12:55
  • This does have a use to warrant the bloat - `constexpr` nested functions. In particular I use this trick to make a templated `constexpr` version of 'next-power-of-2', using that efficient algorithm that relies on shift's and or's specifically. The pattern is `constexpr int F(int X){ struct impl {static constexpr int G(int Y){...}}; return impl::G( X ... );}`. – Xeren Narcy Jul 06 '17 at 07:40
  • @sbi is there any reason to believe this will be unsupported or deprecated from the language in the future? and are there any performance issues that you are aware of? – Chris Apr 24 '18 at 19:05
  • IMO it's a purely stylistic issue. It's surprising, and thus hard to read and understand. – sbi May 01 '18 at 10:39
  • 1
    Why not to extend this answer with lambda function example? – mrgloom Mar 27 '19 at 14:12
282

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

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 7
    Ah, that's neat! I didn't think of it. This is much better than my idea, `+1` from me. – sbi Dec 01 '10 at 13:32
  • 1
    @sbi: I’ve actually used local structs to simulate this in the past (yes, I’m suitably ashamed of myself). But the usefulness is limited by the fact that local structs don’t create a closure, i.e. you cannot access local variables in them. You need to pass and store them explicitly via a constructor. – Konrad Rudolph Dec 01 '10 at 13:34
  • 1
    @Konrad: Another problem with them is that in C++98 you mustn't use local types as template parameters. I think C++1x has lifted that restriction, though. (Or was that C++03?) – sbi Dec 01 '10 at 13:36
  • @sbi: Local type still have internal linkage in 03; 0x gives them external linkage so they can be used as template arguments. – Fred Nurk Dec 01 '10 at 13:44
  • @Fred: So it was C++1x that "fixed" this. – sbi Dec 01 '10 at 16:18
  • @sbi: I don't understand why you keep calling it C++1x; isn't C++ confusing enough without changing the name of C++0x, regardless of what year it is? – Fred Nurk Dec 01 '10 at 17:25
  • I'd almost think we should start going by ISO editions (98 is edition 1, 03 is 2) rather than years; except ISO includes years in document names and there's precedent for 98 and 03. – Fred Nurk Dec 01 '10 at 17:27
  • @Fred: The 'x' denotes the part of its name we don't know yet. Current estimates expect the next standard to be released in either 2011 or 2012, which means its name will be either C++11 or C++12. With "C++1" being fix (we certainly won't have to wait another decade), that only leaves the last digit unknown. I don't plan to call the next TR/TC anything. For the last ones, I've only ever had to name them _after_ their release date was known. (BTW, I think we should stick to using the years to name the standard editions, because that's compatible with C's naming.) – sbi Dec 01 '10 at 17:28
  • @Konrad - good point. I would take a Devil's advocate position and argue that I wouldn't use lambdas in place of nested functions. I come very biased from Pascal and Ada, and for me, nested functions are meant for decomposing and managing the structure of very complex (but highly cohesive) blocks of code. Lambdas are more appropriate for parametrization of algorithms (possibly of general use). Obviously, there is no black-n-white divide between these two goals. But I'd see the former for keeping a structure composable yet private. The later is for exposing structure for reuse. – luis.espinal Dec 01 '10 at 17:30
  • @sbi: I understood that you use 1x to refer to 2011 or 2012; I don't understand why you want to increase confusion rather than continue to use the established name — even Bjarne admits "0x" isn't strictly applicable anymore, but still [suggests continuing to use it:](http://www2.research.att.com/~bs/C++0xFAQ.html) "The name 'C++0x' is a relict of the days where I and others, hoped for a C++08 or C++09. However, to minimize confusion, I'll keep referring to the upcoming C++ standard with the feature set defined here as C++0x." – Fred Nurk Dec 01 '10 at 17:32
  • @luis: Nested functions are often treated equivalently to lambdas (e.g. closures) in other languages that have both (e.g. Python, Javascript). However, even without that, I see no value, for C++ code, in the distinction you make — similarly to how I see no value in distinguishing between classes defined with 'struct' vs classes defined with 'class'. – Fred Nurk Dec 01 '10 at 17:44
  • @Fred: `` And I find it more confusing when "C++0x" refers to "C++11". "C++1x" is the proper term, the rest is history. And, yes, I knew Stroustrup disagrees, but even though he's a nice and wise person, sometimes I still disagree with him. – sbi Dec 01 '10 at 17:47
  • @Fred: Well, in Python and JavaScript, there is simply no distinction. All functions, nested or otherwise, are first-value objects. As for C++, the distinction I make is a matter of stating `intention` in the code design: nested functions are for internal structure not meant for external consumption. In C++0x, lambdas are the extension points for algorithms designed for external consumption. Both state syntactic `and semantic differences` **IN** the design. As for defining classes with `struct` in C++, that's an ugly language language with no redeemable value (other than to confuse people.) – luis.espinal Dec 01 '10 at 18:13
  • @luis: You're free to attach unnecessary and insufficient meaning to any language construct, just as people do for 'struct' vs 'class', of course. – Fred Nurk Dec 01 '10 at 18:25
  • @Fred - obviously since you have a practical and infallible, generally applicable and bullet proof method for determining what is `unnecessary and insufficient`, I'll bow to the self-evidence of your unassailable retort. – luis.espinal Dec 01 '10 at 18:32
  • @luis: Just look at your own comment: "the distinction *I* make", stating lambdas are designed for one narrow, specific use. You're purposefully ignoring how the language treats lambdas and how other code may make use of them — in my experience, this only leads to *unnecessary argument* when communicating with other programmers who don't bury their head in the sand in exactly the same way, because your code *insufficiently expresses* your intention. – Fred Nurk Dec 01 '10 at 18:47
  • @greyfade: That's an old hat, really, but here you go: If it was hexadecimal, it would have to be "C++0xx". – sbi Dec 01 '10 at 18:51
  • @Fred - you are making way too many assumptions about the comment I made. Obviously when the pedal meets the metal one chooses design and implementation that are more appropriate for the task at hand. But in general, I would not use ***an expression*** (something that one naturally ***passes*** around) to manage the structure of a function. That doesn't lead to *unnecessary arguments*. What leads to *unnecessary arguments* are one-line retorts (like the one you did). If you instead opted to express your opinion constructively (as you did now), then one can have an engineering discussion. – luis.espinal Dec 01 '10 at 19:23
  • @Fred - con't. And I don't see how making that separation (lambda expressions vs nested functions) *insufficient*. Insufficient certainly if that's all one have (and I don't see how that can be deduced from my previous comment). That design decision would also accompany other decisions if/when it makes sense. That, *in my experience* does not itself lead to neither *unnecessary argument* nor *insufficient design/intent expression* (since the later, again IMOE, is the result of far more important factors.) – luis.espinal Dec 01 '10 at 19:27
  • 3
    @luis: I must agree with Fred. You are attaching a meaning to lambdas which they simply don’t have (neither in C++ nor in other languages that I’ve worked with – which *don’t* include Python and Ada, for the record). Furthermore, making that distinction is just not meaningful in C++ because C++ does not have local functions, period. It only has lambdas. If you want to limit the scope of a function-like thing to a function, your only choices are lambdas or the local struct mentioned in other answers. I’d say that the latter is rather too convoluted to be of any practical interest. – Konrad Rudolph Dec 02 '10 at 10:04
  • @Fred Nurk: Local types won't be external by default, they will derive linkage from the enclosing function. – Sebastian Mach Feb 22 '11 at 14:26
  • @phresnel: Don't enclosing functions have external linkage by default? – Fred Nurk Feb 22 '11 at 14:45
  • @Fred Nurk: Yes, but that is orthogonal to your phrase `0x gives them external linkage so they can be used as template arguments`. It is more correctly `in 0x local types will inherit linkage by their enclosing function, so types declared within non-static and non-inline functions can be used as template type arguments then`. I.e., in case of static or inline functions, local types can't be template parameters. – Sebastian Mach Feb 23 '11 at 11:33
  • @phresnel: Too much nitpicking. "0x gives them" => "0x allows them to have" – Fred Nurk Feb 23 '11 at 23:40
  • Lambdas and closures are quite different concepts, please don't mix them. C++ supports the former, but not the latter. – GetFree Apr 20 '17 at 12:16
  • @GetFree C++ supports both. The example in my answer is a lambda, but I could easily transform into a closure by adding a capture. – Konrad Rudolph Apr 20 '17 at 12:39
  • @KonradRudolph, capturing variables is not what a closure is. A closure is a whole scope which keeps existing (even local scopes) after its end, becoming a permanent scope for the enclosed function. C++ doesn't support that. – GetFree Apr 20 '17 at 15:16
  • @GetFree C++ closures *do* capture a scope, it’s just a dedicated scope. I do see why you’d *occasionally* want to distinguish subtypes of closures, but (1) for most intents and purposes the distinction *doesn’t* matter, (2) C++ closures solve the same problem that closures in other languages solve, and (3) “closure” is the general name given to this construct, [both inside the context of C++ and outside](https://en.wikipedia.org/wiki/Closure_%28computer_programming%29#Lexical_environment). – Konrad Rudolph Apr 20 '17 at 15:44
  • @KonradRudolph, you are confusing concepts. C++ lambdas can only capture individual values. They do not bind to the scope in which they were defined. – GetFree Apr 20 '17 at 18:17
  • @GetFree No I'm not. C++ lambdas can capture multiple values. But even if they didn't that wouldn't make them not closures. You're making up definitions arbitrarily. – Konrad Rudolph Apr 20 '17 at 18:21
  • @KonradRudolph, correct, they capture values, they don't bind to a scope. That's what a closure is, a scope bound to one or more functions. C++ can't do that. – GetFree Apr 20 '17 at 21:37
  • @GetFree They do both. … This is pointless. You're not listening. – Konrad Rudolph Apr 20 '17 at 22:25
  • @KonradRudolph, you still don't realize the difference. Example: If there are two functions inside a scope, both functions are bound to it so that if one function modify variables in the scope, the other function sees the changes, because the functions are BOUND TO the scope. In C++ you don't have that, there's no scope binding. C++ lambas only copy values at the moment of the function's definition. On the other hand, capture by reference isn't able to capture anything, because as soon as those variables go out of scope, the captured references become invalid. – GetFree Apr 21 '17 at 01:10
  • @GetFree As I said, that’s a valid distinction (and, as I also said, I *realise* the difference). But it’s *simply untrue* that one kind defines a closure and the other does not, just because the scope closed-over in C++ is private to an individual function. You are *making up* an overly restrictive definition to argue that C++ has no closures. Suit yourself. But it’s not the conventional definition, and it doesn’t exactly make communication easier if you redefine commonly-used terms willy-nilly to mean something else. – Konrad Rudolph Apr 21 '17 at 11:58
  • @KonradRudolph, you are insisting with common misconceptions. Your use of the word "conventional" shows that. Overgeneralization leads to that kind of confusion. Too much Wikipedia, perhaps. – GetFree Apr 21 '17 at 14:16
  • Dear KonradRudolph and @GetFree, while your discussion is quite emotional and not very helpful for the reader, I have to agree that a C++ lambda with captures is not quite what is called closures in functional programming: The important point is that the lifetime of captured references are not extended by the lifetime of the lambda object. While that would be quite unnatural in C++, it is an important mechanism to create state shared by and private to one or more lambda functions in functional programming. In OO, such shared state is probably better put into a class object. – mdr Nov 10 '17 at 09:36
  • Dear @KonradRudolph: See my comment above. – mdr Nov 10 '17 at 09:37
  • ...thinking about it: You CAN achieve the extension of lifetime: Change your auto-variable to a shared pointer to the desired data. Capture the shared_ptr in the lambda by value/copy. – mdr Nov 10 '17 at 09:41
  • In C#, lambda and anonymous functions had worse performance than local functions. Local functions in C# are actually just normally functions moved outside of the host function and prevented from being used else where, hence why they preformed equally as well. Are there performance tolls from C++ lambdas that would discourage from using this? – AustinWBryan Jun 14 '18 at 00:00
  • 2
    @AustinWBryan No, lambdas in C++ are just syntactic sugar for functors and have zero overhead. There's a question with more detail somewhere on this website. – Konrad Rudolph Jun 14 '18 at 00:10
54

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;
};

For a recursive function, compile-time type deduction is not supported:

function<int(int)> factorial{ [&](int n)
{
        return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n;
} };
Scover
  • 93
  • 9
Sebastian Mach
  • 38,570
  • 8
  • 95
  • 130
  • 1
    Should be `operator () (unsigned int val)`, your missing a set of parentheses. – Joe D Dec 01 '10 at 14:55
  • 1
    Actually, this is a perfectly reasonable thing to do if you need to pass this functor to an stl function or algorithm, like `std::sort()`, or `std::for_each()`. – Dima Dec 01 '10 at 16:18
  • 1
    @Dima: Unfortunately, in C++03, locally defined types cannot be used as template arguments. C++0x fixes this, but also provides the much nicer solutions of lambdas, so you still wouldn't do that. – Ben Voigt Dec 02 '10 at 20:31
  • Oops, you are right. My bad. But still, this is not just a funny trick. It would have been a useful thing if it were allowed. :) – Dima Dec 02 '10 at 20:34
  • 3
    Recursion is supported. However, you can't use ```auto``` to declare the variable. Stroustrup gives the example: ```function rev=[](char*b, char*e) { if( 1 – Eponymous Aug 20 '14 at 15:11
  • Wow the struct-operator solution was a neat trick. Are there any drawbacks or pitfalls of using it? – mathreadler Dec 07 '17 at 06:50
  • @mathreadler: From a maintenance point of view, in particular the principle of least surprise, it is not common/idiomatic C++. – Sebastian Mach Dec 07 '17 at 08:53
  • @SebastianMach : Ok, then I will only use it when people deserve to be surprised if they get to read it. =) – mathreadler Dec 07 '17 at 09:13
  • @mathreadler: Haha, good idea. Stuff like this also gives you bragging rights before your colleaques :P – Sebastian Mach Dec 07 '17 at 09:14
  • @Sebastian Mach: No, I mean my own code, not which others are supposed to be able to read ;) – mathreadler Dec 07 '17 at 09:56
27

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;
}
Donald Duck
  • 8,409
  • 22
  • 75
  • 99
20

No.

What are you trying to do?

workaround:

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

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

}
Nim
  • 33,299
  • 2
  • 62
  • 101
  • 2
    Note that the class instantiation approach comes with a memory allocation and is therefore dominated by the static approach. – ManuelSchneid3r May 18 '18 at 19:34
  • @ManuelSchneid3r, not in C++. `foo` is [trivially default-constructible](http://www.cplusplus.com/reference/type_traits/is_trivially_default_constructible/). It does not have a zero size despite having no members, as the standard does not allow zero-sized struct types, but unless you count subtracting a constant from the stack pointer register as an "allocation" (which will be [eliminated by any sensible compiler at the `-O1` level](https://godbolt.org/z/P495dx) anyway), it's free. I'm not saying that it's not ugly; my point is that it's free of allocation. :) – kkm inactive - support strike Feb 24 '21 at 09:15
  • IMO, nicer to make it a static function, then go `foo::f()`. Upvoted anyway, since this was def the most straightforward way to do it in C++03. – Keith Russell Mar 04 '21 at 18:57
17

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();
}
xeruf
  • 2,602
  • 1
  • 25
  • 48
Leo Davidson
  • 6,093
  • 1
  • 27
  • 29
  • Not sure you can, except by creating an object instead (which adds just as much noise, IMO). Unless there's some clever thing you can do with namespaces, but I can't think of it and it's probably not a good idea to abuse the language any more than what we are already. :) – Leo Davidson Dec 02 '10 at 12:31
  • The getting-rid-of-dummy:: is in one of the other answers. – Sebastian Mach Feb 22 '11 at 14:23
12

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.

Thomas Owens
  • 114,398
  • 98
  • 311
  • 431
  • 2
    It is supported by the GNU C compiler, as a special extension. But only for C, not C++. – TonyK Dec 01 '10 at 13:29
  • Ah. I don't have any special extensions in my C compiler. That's good to know, though. I'll add that titbit to my answer. – Thomas Owens Dec 01 '10 at 13:30
  • I've used the gcc extension for support of nested functions (in C, though, not C++). Nested functions are a nifty thing (as in Pascal and Ada) for managing complex, yet cohesive structures that are not meant to be of general use. As long as one uses the gcc toolchain, it is assured to be *mostly* portable to all targeted architectures. But if there is change of having to compile the resulting code with a non-gcc compiler, then, it is best to avoid such extensions and stick as close as possible to the ansi/posix mantra. – luis.espinal Dec 01 '10 at 17:34
9

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

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
9

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.

luis.espinal
  • 10,331
  • 6
  • 39
  • 55
8

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.

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
royas
  • 4,846
  • 2
  • 16
  • 12
  • Now I think this is the best answer. Although it is possible to declare a function within a function (which I use all the time,) it is not a local function as defined in many other languages. It is still good to know of the possibility. – Alexis Wilke Jul 06 '16 at 16:05
5

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.

Barney Szabolcs
  • 11,846
  • 12
  • 66
  • 91
3

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

Community
  • 1
  • 1
trig-ger
  • 1,195
  • 1
  • 11
  • 18
  • Most Vexing Parse is IMO one of the worst parts of C++. Also IMO, it is a consequence of another one of the worst parts of C++: function declaration syntax -- which is a consequence, IMO, of adherence, of the `*` in declarations, to names, instead of being part of the type. That is, `int* a, b` declares one `int*` and one `int`, instead of two `int*`s. >:( – Keith Russell Mar 04 '21 at 19:00
  • Also, I am unaware of any purpose the optional parens around variable names in declarations serve, except as a workaround for the dumb behavior of `*` in declarations. IMO, a function pointer declaration ought to look like this: `int(int)* b` -- I do not understand why it needed to be `int(*b)(int)` instead. – Keith Russell Mar 04 '21 at 19:04
3

Yes, and you can do things with them that even C++20 Lambdas don't support. Namely, pure recursive calls to themselves & related functions.

For example, the Collatz Conjecture is that a certain simple recursive function will ultimately produce "1" for ANY positive integer N. Using an explicit local struct and functions, I can write a single self-contained function to run the test for any "N".

constexpr std::optional<int> testCollatzConjecture(int N) { 
    struct CollatzCallbacks {
        constexpr static int onEven(int n) {
            return recurse(n >> 1); // AKA "n/2"
        }
        constexpr static int onOdd(int n) {
            if(n==1) return 1;     // Break recursion. n==1 is only possible when n is odd.
            return recurse(3 * n + 1);
        }
        constexpr static int recurse(int n) {
            return (n%2) ? onOdd(n) : onEven(n); // (n%2) == 1 when n is odd                
        }
    };

    // Error check
    if(N < 0) return {};

    // Recursive call.
    return CollatzCallbacks::recurse(N);
}

Notice some things that even c++20 lambdas couldn't do here:

  1. I didn't need std::function<> glue OR lambda captures ("[&]") just to enable my local recursive functions call themselves, or each other. I needed 3 plain-old-functions with names, and that's all I had to write.
  2. My code is more readable and (due to (1)) will also run much faster.
  3. I cleanly separate the recursive logic in "CollatzCallbacks" from the rest of "testCollatzConjecture". It all runs in an isolated sandbox.
  4. I was able to make everything "constexpr" and state-less, so it can all run at compile time for any constant value. AFAIK I'd need c++23 just to achieve the recursion part with state-less lambdas.

Remember: Lambda functions are really just compiler-generated local structs like "CollatzCallbacks", only they're unnamed and only have a single "operator()" member function. You can always write more complex local structs and functions directly, especially in cases like this where you really need them.

zyezek
  • 31
  • 1