Cooking lambda functions in C ++ - Part 1

С++, лямбда функция

My favorite tool in C ++ is lambda functions, although somehow they told me that they seem scary. In fact they are lovely. They greatly simplify the writing of programs and allow you to make quite interesting decisions.

But before considering various ways of using lambda functions, I suggest to familiarize yourself with the basic syntax of lambda functions.

Possible options for the syntax of lambda functions

[ capture ] ( params ) mutable exception attribute -> ret { body }
[ capture ] ( params ) -> ret { body }
[ capture ] ( params ) { body }
[ capture ] { body }

The first option is complete, but it is not forbidden to use abbreviated variations in the recording of functions.

  • capture - list of external capture objects, they can be captured both by reference and by copying.
  • params - list of parameters passed to the lambda function, this part will be similar to writing arguments for normal functions.
  • mutable - Using mutable allows you to modify copies of objects that have been captured by copying. In the normal version, they will not be modified.
  • exception - provides an exception specification, that is, lambda functions as well as normal functions can throw exceptions.
  • attribute - provides an attribute specification, there are only two such attributes defined in the C ++ specification ([[noreturn]], [[carries_dependency]])
    • params - list of parameters passed to the lambda function
    • ret - the return value of the lambda function

As for the return value, it can be automatically output from the object type, which is returned by the return statement. If the lambda function does not have a return statement, then the return value will be void.

The lambda function creates an unnamed temporary object of a unique unnamed non-union, non-aggregate type, known as a closure type. Thanks to the introduction of the auto operator in the modern C ++ standard, it is possible to declare the lambda object object fairly easily, without writing a std :: function declaration with all aprams and return values, which makes the code more simple and readable (for an experienced programmer, of course. that the newcomer will quickly suspect that something is wrong if the std :: function appears in the lambda declaration, but this is already a matter of practice).

Here is an example of declaring a simple lambda function that will return a void type, since at least one return statement is missing.

#include <iostream>

using namespace std;

int main()
{
    auto myLambda = []()
    {
        cout << "Hello World!" << endl;
    };

    myLambda();

    return 0;
}

Accordingly, the program code is not compiled if there are two or more return statements in the lambda function that will return objects of different types that are not connected by an inheritance hierarchy and which can not be reduced to a base class type. And even if these objects have a base class, it will be necessary to register the type of the return value, it will just be a pointer to the object of the base class (in the general case).

Here is an example of code that will not compile.

#include <iostream>

using namespace std;

class A
{
public:
    A(){}
};

class B : public A
{
public:
    B(){}
};

class C : public A
{
public:
    C(){}
};

int main()
{
    auto myLambda = [](int type)
    {
        if (type == 0)
        {
            return new B();
        }
        else
        {
            return new C();
        }
    };

    myLambda(0);

    return 0;
}

You must specify the return type

auto myLambda = [](int type) -> A* // Let's specify the type of the return value
{
    if (type == 0)
    {
        return new B();
    }
    else
    {
        return new C();
    }
};

Also, the compilation error will occur if you do not specify the return type and you create an object inside the lambda function in the heap, but in some cases you can return the pointer to nullptr . That is, the following code is not compiled.

#include <iostream>

using namespace std;

class A
{
public:
    A(){}
};


int main()
{
auto myLambda = [](int type)
{
    if (type == 0)
    {
        return new A();
    }
    else
    {
        return nullptr;
    }
};

    myLambda(0);

    return 0;
}

Again you need to specify the type of the return value

auto myLambda = [](int type) -> A* // Let's specify the type of the return value
{
    if (type == 0)
    {
        return new A();
    }
    else
    {
        return nullptr;
    }
};

The fact is that nullptr is a universal data type, which in some sense is not a data type, because it can not be set as a variable type. But it can be assigned as a value to a pointer to an object. In order for the implicit conversion to occur correctly in this case, you must also specify the type of the return value.

Also in the above example, we show how to call a lambda function and pass parameters to it. Noticed? In this example, the int type parameter is used, depending on which we return a pointer to the created object or nullptr .

Also in lambda functions there is the concept of capturing variables. This means that the lambda function can use not only variables that are passed to it as parameters, but also any objects that have been declared outside the lambda function.

The symbol list can be transferred as follows:

  • [a,&b] where a is captured by value, and b is captured by reference.
  • [this] grabs the this pointer by value.
  • [&] capture all characters by reference
  • [=] capture all characters by value
  • [] nothing captures

About the capture of variables, let's talk in the next articles.

But I note one interesting point, the lamda function can be called immediately where you declared it, if you add parentheses after the body of the lame function and pass all the necessary parameters, if any.

For example, this code is also compiled

#include <iostream>

using namespace std;

class A
{
public:
    A(){}
};


int main()
{

    A* myA = [](int type) -> A*
    {
        if (type == 0)
        {
            return new A();
        }
        else
        {
            return nullptr;
        }
    }(0);

    return 0;
}

So think about whether the following code is compiled?

int main(){[](){}();}
We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate

Comments

Only authorized users can post comments.
Please, Log in or Sign up
Donate

Hello, Dear Users of EVILEG!!!

If the site helped you, then support the development of the site financially, please.

You can do it by following ways:

Thank you, Evgenii Legotckoi

a
Feb. 25, 2020, 4:40 a.m.
ayb

C++ - Test 005. Structures and Classes

  • Result:83points,
  • Rating points4
DZ
Feb. 24, 2020, 1:47 p.m.
Dmitrij Zlobin

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:40points,
  • Rating points-8
p
Feb. 17, 2020, 1:41 p.m.
pstMem

C++ - Тест 003. Условия и циклы

  • Result:85points,
  • Rating points6
Last comments
Feb. 24, 2020, 2:54 a.m.
Evgenij Legotskoj

Добрый день. Там будет url, на который указывает ссылка тега a в пагинаторе, если правильно помню )) Написал этот код и забыл.
B
Feb. 23, 2020, 11:37 p.m.
BahaMeirman

Евгений Здравствуйте! Не могу понять вот эту часть кода: url: jQuery(this).attr('action') наверное здесь должен быть путь к url, тогда 'action' на какой url указывает?
Feb. 17, 2020, 2:22 a.m.
Evgenij Legotskoj

Добрый день. Это кастомный тег, помещается в файл, который находится в каталоге templatetags myapp/ templatetags/ myapp.py
B
Feb. 16, 2020, 12:36 p.m.
BahaMeirman

Добрый вечер! Монжно по подробней о теге get_companion? ссылка не работает.
Now discuss on the forum
a
Feb. 25, 2020, 7:06 a.m.
ayb

Да
Feb. 24, 2020, 11:04 a.m.
Evgenij Legotskoj

Добрый день. Вот пример с дружественного ресурса с движением камеры
Feb. 24, 2020, 5:29 a.m.
Evgenij Legotskoj

Qt не предоставляет функционала по запросу root прав во время выполнения программы. Поэтому нужно использовать платформозависимый функционал, для Linux это будет выглядеть так: #include…
Feb. 24, 2020, 2:47 a.m.
Evgenij Legotskoj

Добрый день. Что означает клиентская область? Это изображение? Вам нужно распознавать символы текста или всё-таки пользователь будет вводить текст с клавиатуры, просто в любом месте "абстр…
VZ
Feb. 21, 2020, 4:19 a.m.
Vladimir Zhitkovsky

void sendImage(int sessid, int type, int dest, int format, QString imgBase64Data){ QNetworkRequest request; request.setUrl(QUrl(ipAddress + "ctlapi/cmd=preparereportimg&sessid=…
EVILEG
About
Services
© EVILEG 2015-2019
Recommend hosting TIMEWEB