How to write a local functions in C++

C++ does not directly allow nested (local) functions like this:

void setup ()
  {
  // local function
  int add (const int a, const int b)
      {
      return a + b;
      }

  Serial.begin (115200);
  int i = add (3, 4);
  Serial.println (i);
  }  // end of setup

void loop () { }

This gives the error:

sketch_oct13c.ino: In function 'void setup()':
sketch_oct13c:6: error: a function-definition is not allowed here before '{' token
sketch_oct13c:11: error: 'add' was not declared in this scope

However if you want to have a local function you can achieve it with a function object. Example:

void setup ()
  {
  struct
    {
    int operator () (const int a, const int b)
      {
      return a + b;
      }
    } add;
 
  Serial.begin (115200);
  int i = add (3, 4);
  Serial.println (i);
  }  // end of setup

void loop () { }

This compiles OK, and prints the correct answer (7).

The advantage of this is that you do not clutter "global scope" with functions which may only be required as helper functions to other functions.


You can also use function objects to have a function with a "state". That is, a function that remembers one or more things that are relevant to it. For example, a currency converter which remembers the currency rate:

void setup ()
  {
  class converter
    {
    float rate_;
    
    public:
    converter (const float rate) : rate_ (rate) { };
    
    float operator () (const float amount)
      {
      return amount * rate_;
      }
    };  // end of converter class
 
  Serial.begin (115200);
  
  converter yen (98.48);
  converter euro (0.74);
  
  for (float dollar = 0; dollar <= 10; dollar++)
    {
    Serial.print ("$");
    Serial.print (dollar);
    Serial.print (" is ");
    Serial.print (yen (dollar));
    Serial.print (" Yen, and "); 
    Serial.print (euro (dollar));
    Serial.println (" Euro.");
    }  // end of for
  
  }  // end of setup

void loop () { }

Output:

$0.00 is 0.00 Yen, and 0.00 Euro.
$1.00 is 98.48 Yen, and 0.74 Euro.
$2.00 is 196.96 Yen, and 1.48 Euro.
$3.00 is 295.44 Yen, and 2.22 Euro.
$4.00 is 393.92 Yen, and 2.96 Euro.
$5.00 is 492.40 Yen, and 3.70 Euro.
$6.00 is 590.88 Yen, and 4.44 Euro.
$7.00 is 689.36 Yen, and 5.18 Euro.
$8.00 is 787.84 Yen, and 5.92 Euro.
$9.00 is 886.32 Yen, and 6.66 Euro.
$10.00 is 984.80 Yen, and 7.40 Euro.

In this example the single "converter" function "remembers" the rate for the two currencies in its "rate_" variable.

That's awesome, thanks Nick.

It is nice that it is possible, but I do not like the readability of it as the code of setup() or whatever can become very large.

an elaborated discussion see - GotW #58: Nested Functions -

The page you linked raises some interesting issues, including the lack of access to variables from the enclosing function.

I'm not necessarily recommending that this be done as a blanket thing, but the localization of a function could be useful under certain circumstances. For example, a sort comparison callback.

Found this wrapper trick - Simulating nested functions in C++ - Stack Overflow -

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

void setup() 
{
  Serial.begin(115200);
  Serial.println("Start ");
  
  lambda(int, (int x, int y) { return x > y ? x : y; } ) maxFunc;
  int m = maxFunc(1,2); //=> 2
  
  Serial.println(m); 
}

void loop() 
{
}

A call for maxFunc() from within loop fails to compile.