Borbin the 🐱

C++ function inside a function

30 November, 2024


The C++ standard does not allow the usage of a function inside another function. Instead, a lambda expression can be used to achieve this functionality.

For instance, it is not permissible to define this function within another function. However, you can achieve the same functionality by using a lambda expression as follows:

// function definition
BYTE grey_sum(int x, int y)
{
    const int index(3 * ((rect_y + y) * requested_data2.picture_width + rect_x + x));
    const BYTE grey(data[index]);
    return grey;
}


The lambda syntax starts with the capture clause [=] to have read access on all the variables in the scope (use an empty clause [] to access only local variables, or use [&] to use all the variables as references, or list explicitly which variables are used by value and which by reference, for example: [a, &b]), the argument list (int x, int y) and then the return type -> BYTE. The mutable specification and the exception specification are optional and not used here.
The lambda is then used like a function: grey_sum1 += grey_sum(x1, y1);

// equivalent lambda definition
auto grey_sum = [=](int x, int y) -> BYTE
    {
        const int index(3 * ((rect_y + y) * requested_data2.picture_width + rect_x + x));
        const BYTE grey(data[index]);
        return grey;
    };


See this example from the AsciiArt plugin for cPicture (github link).
Using a traditional function would necessitate passing all local data as arguments, which can be inefficient. In contrast, a lambda expression provides a more streamlined and effective approach by capturing local variables directly within its scope.

    // Lambda to calculate the grey value.
    auto grey_sum = [=](int x, int y) -> BYTE
        {
            const int index(3 * ((rect_y + y) * requested_data2.picture_width + rect_x + x));
            const BYTE grey(data[index]);
            return grey;
        };

    // Read the rect segment at (rect_x, rect_y).
    for (register int y1 = 0; y1 < rect_h / 2; y1++)
    {
        for (register int x1 = 0; x1 < rect_w / 2; x1++)
            grey_sum1 += grey_sum(x1, y1);

        for (register int x2 = rect_w / 2; x2 < rect_w; x2++)
            grey_sum2 += grey_sum(x2, y1);
    }
    for (register int y2 = rect_h / 2; y2 < rect_h; y2++)
    {
        for (register int x1 = 0; x1 < rect_w / 2; x1++)
            grey_sum3 += grey_sum(x1, y2);

        for (register int x2 = rect_w / 2; x2 < rect_w; x2++)
            grey_sum4 += grey_sum(x2, y2);
    }

    const int rect_area4 = rect_area / 4;

    // Lambda to check if the contrast and brightness adjusted grey sum exceeds the threshold.
    auto match = [=](__int64 grey_sum) -> bool
        {
            return ((grey_sum / rect_area4 - 127) * (100 - contrast) / 100 + brightness + 127) <= 127;
        };

    // rect area is divided into 4 equal parts
    // 12
    // 34
    const bool b1 = match(grey_sum1);
    const bool b2 = match(grey_sum2);
    const bool b3 = match(grey_sum3);
    const bool b4 = match(grey_sum4);