28

In C the following code works in gcc.

int foo( int foo_var )
{
 /*code*/
  int bar( int bar_var )  
  {
    /*code*/
    return bar_var;
  }
  return bar(foo_var);
}

How can I achieve the same functionality of nested functions in C++ with the gcc compiler? Don't mind if this seems like a beginner question. I am new to this site.

jparanich
  • 8,372
  • 4
  • 26
  • 34
Paul McCutcheon
  • 283
  • 1
  • 3
  • 4
  • 1
    If you need this feature in **C**, you're propably misusing the language anyway. And even if not, a solution that at least work on the major compilers, if not somethinge entirely standard, would be vastly preferrable to what's basically a very rare compiler-specific extension. –  Mar 18 '11 at 18:08
  • 5
    +1 Wow, I didn't know this was possible! Thanks for making me learn something new ^^! – helpermethod Mar 18 '11 at 18:08
  • and... the conversion to CW is broken (6 identical edits triggered it). Is this already a known issue on meta that I can upvote? – Ben Voigt Mar 18 '11 at 18:10
  • 1
    @Ben: the conversion seems to have been triggered by 5 different editors all editing (even though their changes were largely identical, this counts). However, there's another oddity in the revision history that doesn't make so much sense. See: http://meta.stackexchange.com/questions/83772/why-is-the-cw-conversion-attributed-to-a-commenter – Shog9 Mar 18 '11 at 19:28
  • 1
    possible duplicate of [C++ can we have functions inside functions?](http://stackoverflow.com/questions/4324763/c-can-we-have-functions-inside-functions). Answers there also covers the how to. – Ciro Santilli OurBigBook.com Jun 27 '15 at 08:10

8 Answers8

36

Local functions are not allowed in C++, but local classes are and function are allowed in local classes. So:

int foo( int foo_var )
{
 /*code*/
  struct local 
  {
    static int bar( int bar_var )  
    {
      /*code*/
      return bar_var;
    }
  };
  return local::bar(foo_var);
}

In C++0x, you would also have the option of creating a functor using lambda syntax. That's a little more complicated in C++03, but still not bad if you don't need to capture variables:

int foo( int foo_var )
{
 /*code*/
  struct bar_functor
  {
    int operator()( int bar_var )  
    {
      /*code*/
      return bar_var;
    }
  } bar;
  return bar(foo_var);
}
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • +1. I sometime use local struct as an alternative to nested function! – Nawaz Mar 18 '11 at 18:07
  • 2
    Missing `static` on the member function? – aschepler Mar 18 '11 at 18:07
  • @aschepler: On the first one, yeah I was. Thanks, now fixed. – Ben Voigt Mar 18 '11 at 18:10
  • Just to be pedantic - you need a semicolon after the closing brace of struct local. You do on my compiler, at least (Borland/CodeGear). – drkvogel Jan 06 '14 at 16:53
  • @drkvogel: You are correct -- I'm not declaring a variable in that code snippet, so the semicolon immediately follows the closing brace (contrast with `bar_functor` where a variable is declared). – Ben Voigt Jan 06 '14 at 17:10
  • 1
    @TheMask: You can add data members to the class. To share data between the function and the nested function, you can either put them in the class and have the outer function access them through an instance, or put reference inside the class. The first is called *hoisting*, and is what the C# compiler does to create closures. The second is what C++11 prefers when it creates lambdas. Naturally with C++ capture-by-reference closures (with or without lambda syntax) you have to worry about object lifetime. – Ben Voigt Mar 29 '14 at 15:27
  • gcc local functions capture variables, while neither of the above do: so not a drop-in replacement. – Yakk - Adam Nevraumont Jul 09 '14 at 20:46
  • @Yakk: Yes, they do, but not automatically. Two variations described in my comment to TheMask. – Ben Voigt Jul 10 '14 at 01:53
12

Turn your function into a functor as Herb Sutter suggests in this article

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
  • 1
    I don't understand. This is just a very concise version (with a link) of the answer right below it, and that one has no down votes. By what criteria is this answer to be downvoted but not the other? – GManNickG Mar 18 '11 at 18:26
  • 23
    It's a good link, but you could really have improved this answer by *demonstrating it* [as Ben did in his answer.](http://stackoverflow.com/questions/5356050/simulating-nested-functions-in-c/5356065#5356065) Link-only answers are... kinda icky. No matter how good the link is, the answer becomes utterly worthless if it ever breaks. – Shog9 Mar 18 '11 at 18:27
  • @GMan : I dont know how my answer got accepted. The link is very useful and deals with different possible methods to achieve the same. – Prasoon Saurav Mar 18 '11 at 18:28
  • @Shog9: That doesn't make it worthy of down-voting though, so I'm still confused. (That reasoning is just shy of: every answer but the top one should be down-voted, for not being as good as the top answer; which is patently absurd.) – GManNickG Mar 18 '11 at 18:29
  • 1
    @Shog9 : I see no point is repeating something which has already been demonstrated in a very good manner somewhere. That's why shared the link. – Prasoon Saurav Mar 18 '11 at 18:29
  • 2
    @GMan: Did I say I down-voted it? @Prasoon: if you aren't interested in improving your answer, don't ask for an explanation for down-votes. Whoever down-voted it has long ago moved on - any explanation you get will be from a 3rd-party such as myself. If you're just fishing for sympathy, then I shouldn't have bothered. – Shog9 Mar 18 '11 at 18:34
  • 2
    @Shog9: Did I say you did? (No; in fact I took great care *not* to imply that, an apparently wasted effort.) – GManNickG Mar 18 '11 at 18:35
  • @GMan: you're addressing me in a comment wholly concerned with the down-vote and entirely unconcerned with the content itself. If I misunderstood you, may I ask what your point *really* was? – Shog9 Mar 18 '11 at 18:36
  • @Prasoon: and I never accused you of doing so (I combined two responses into one comment, perhaps a mistake). I'm merely pointing out that you asked for clarification - accept it or ignore it, there's no point in arguing. – Shog9 Mar 18 '11 at 18:38
  • @Shog9: To address your objections to the answer. If those coincided with the down-voter reason (not an arbitrary coincidence), then I would have jointly replied to him as well. Otherwise, it remains a reply to your objections. – GManNickG Mar 18 '11 at 18:41
  • @GMan: ok, look - if you disagree with anything I wrote, let's discuss that. If you agree, but simply don't feel that the flaws *deserved a down-vote*, then let's drop it - voting is a personal matter, neither of us have any business judging the quality of someone else's vote. – Shog9 Mar 18 '11 at 18:45
  • 2
    I didn't downvote it, but this answer is demonstrably false. (My first code snippet is the demonstration, it is not a functor, and it is wholly contained inside the outer function) s/need to/should/ and the answer becomes true, which is why I'm neither up- nor down-voting it. – Ben Voigt Mar 18 '11 at 18:49
  • @Ben : I precisely mentioned what Herb Sutter has written in his article. "Short answer: Yes, it is possible, with only a little code reorganization and a minor limitation. The basic idea is to **turn a function into a functor** -- and this discussion, not coincidentally, will also serve to nicely illustrate some of the power of functors." – Prasoon Saurav Mar 18 '11 at 18:51
  • @Ben: heh, the link itself actually demonstrates this as well... Totally missed the terminology mistake in the question itself! – Shog9 Mar 18 '11 at 18:52
  • @Shog9: I disagree with the latter. I think one of the bad parts of this site is that it's made voting reasons taboo to discussion. There *are* wrong and stupid reasons to vote either way on answers, and pretending that every reason is equally valid is *wrong*. But let's drop it anyway, because this isn't the place. – GManNickG Mar 18 '11 at 18:52
  • 1
    @Prasoon: "You need to" means "This is the only way to accomplish your goal". In fact, it may be the *best* way, but as long as *any* other way exists, there's no *need* to go with the best way. – Ben Voigt Mar 18 '11 at 18:53
  • 1
    @Ben : Yes right! Removed "You need to". Dont mind my bad English – Prasoon Saurav Mar 18 '11 at 18:56
  • @GMan: It's imprudent to judge the reasons when you can't *know* them. If you're interested in discussing this further, Meta or MSO chat is the place. – Shog9 Mar 18 '11 at 18:56
  • 2
    @Prasoon: +1 for completely correct answer. @GMan, @Shog9: I have no clue who downvoted this, but I suspect the downvotes on two of the other answers came from the same silent killer downvoter. – Ben Voigt Mar 18 '11 at 19:01
  • @Shog9: I'm not sure what you're trying to say there. That I can't enumerate a list of possible objections, and judge them? I don't have to nor have claimed to know the reason for that specific vote reason, but I can conjecture. But my last comment wasn't contingent on any specific reason anyway: just that reasons, when considered, can be marked as good or bad. – GManNickG Mar 18 '11 at 19:03
  • link only answer and now the link is broken. please include something from the source next time. – Ian Ooi Jul 16 '13 at 21:04
  • @IanOoi: The GotW link is fine. If you can't see it you might be having problems with your internet connection. – Ben Voigt Mar 29 '14 at 15:25
11

The construct that comes closest to nested functions is the C++11 lambda.

void SomeFunction(int x)
{
    int var = 2;
    auto lambda = [&] (int param) -> int { return var + param; };

    printf("var + x = %d\n", lambda(x));
}

Lamdas allow to use variables from the outer scope (the [&] specifies to automatically capture all variables from the outer scope by reference). A lambda, that does not use any variables from the outer scope (use []) can be converted to a function pointer of the same type and can thus be passed to functions accepting a function pointer.

Timo
  • 923
  • 9
  • 10
11

use local functor

#define lambda(return_type, function_body) \
struct { return_type operator () function_body }


int main ()
{
    lambda(int, (int x, int y) { return x > y ? x : y; } ) maxFunc;
    int m = maxFunc(1,2); //=> 2
    ...
}
  • +1 I really like the simmplicity of your "C lambda". But if the asker talks about "from C to C++", suggest C++ style (C++11 lambdas) instead of macros :) – Manu343726 Jul 05 '13 at 10:32
3

You could try using boost::phoenix (v2 is a subpackage of spirit, v3 is in svn/trunk as it's own package and should be in 1.47)

#include <boost/spirit/include/phoenix.hpp>
#include <boost/function.hpp>

using namespace boost::phoenix::arg_names;

int foo( int foo_var )
{
 /*code*/
  boost::function<int(int)> bar = _1 + 5;
  return bar(foo_var);
}

int main() {
return foo(1);
}
KitsuneYMG
  • 12,753
  • 4
  • 37
  • 58
  • 1
    @TheMask `_1` is a special type that has all the basic operators overloaded to produce expression-trees instead of doing anything. When a tree is passed arguments with `operator()`, it can walk teh built expression tree and substitute arguments for `_N`. For more info you'll need to beef up on MPL and Boost.Proto quite a bit. – KitsuneYMG Mar 29 '14 at 14:23
1

In C++ you may achieve the same effect by other possible means. There are no direct nested function implementations. Two helpful links:

http://www.respower.com/~earlye/programming/19990916.001.htm

http://www.devx.com/tips/Tip/40841

Bourne
  • 10,094
  • 5
  • 24
  • 51
0

AFAIK, nested functions are not allowed in C++.

activout.se
  • 6,058
  • 4
  • 27
  • 37
0

I know this thread is old. But a C++11 solution would be to write lambdas and call them whenever wanted

Hemil
  • 916
  • 9
  • 27