Evgenii Legotckoi
Evgenii LegotckoiFeb. 13, 2018, 6:13 p.m.

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.

Do you like it? Share on social networks!

Comments

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

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

  • Result:50points,
  • Rating points-4
m

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

  • Result:80points,
  • Rating points4
m

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

  • Result:20points,
  • Rating points-10
Last comments
ИМ
Игорь МаксимовNov. 22, 2024, 10:51 p.m.
Django - Tutorial 017. Customize the login page to Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii LegotckoiNov. 1, 2024, 12:37 a.m.
Django - Lesson 064. How to write a Python Markdown extension Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZEOct. 19, 2024, 6:19 p.m.
Fb3 file reader on Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь МаксимовOct. 5, 2024, 5:51 p.m.
Django - Lesson 064. How to write a Python Markdown extension Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas5July 5, 2024, 9:02 p.m.
QML - Lesson 016. SQLite database and the working with it in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Now discuss on the forum
Evgenii Legotckoi
Evgenii LegotckoiJune 25, 2024, 1:11 a.m.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey1Nov. 15, 2024, 5:04 p.m.
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProjectJune 4, 2022, 1:49 p.m.
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9AnonimOct. 25, 2024, 7:10 p.m.
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

Follow us in social networks