Are Lambdas just classes with an overloaded operator ()?

The more I read about lambdas, the more I hear from people that they simply mask objects / functors (if they don't capture anything, in which case they are just free static functions. I want to write lambdas in the local area and pass them to the universal handler events, which causes them as necessary, and I begin to notice that I can hardly do something that allows me to make a traditional functional object.Please let me know if my understanding of this is wrong, as I commented on a whole bunch the things you can do with functors and can't with lambdas as far as I know:

#include <iostream>
#include <vector>

struct MyFunctorClass
{
    // Custom constructor, can't do with lambda
    MyFunctorClass(int& capturedVariable) : capturedVariable(capturedVariable) 
        { std::cout << "I can do anything on construction.\n"; }

    // Overloading constructors, different ways to initialise function object, can't do with lambda
    MyFunctorClass(int& capturedVariable, int sizeOfBuffer) : capturedVariable(capturedVariable) 
        { heapAllocation = new int[sizeOfBuffer]; }

    // Custom destructor, can't do with lambda
    ~MyFunctorClass() { delete[] heapAllocation; }  

    void operator()() { std::cout << "Standard call\n"; }
    void operator()(int arg) { std::cout << "Argument passed: " << arg << '\n'; }   
    // operator() overloading, different ways to call the function object, can't do with lambda

    int* heapAllocation;                // Have heap allocated resources, can't do with lambda
    bool internalStateVariable = true;  // Initialise a member variable on construction, can't do with lambda
    int& capturedVariable;              // I can access this variable directly with MyFunctorClass::capturedVariable = 7, can't do with lambda
};

int main()
{
    int localVar = 0;
    bool trueOrFalse = false;

    {
        MyFunctorClass* myFunctionObj = new MyFunctorClass(localVar, 100);  
        // Can dynamically allocate function object, can't with lambda
        auto lambda = new[&]() { localVar = 1; };   // Can't do?
        lambda.trueOrFalse = true;      // trueOrFalse isn't member of lambda, even though it captured it, doesn't make sense

    }   // Lambda object is destroyed here. My function object lives until I delete it.

    return 0;
}

void holdFunctionObject(MyFunctorClass* funcObj)
{
    static std::vector<MyFunctorClass*> list;
    list.push_back(funcObj);    
    // I can hold all the function objects forever, they'll never go out of scope unless I delete them, can't do with lambda
}

, , - " ". , , , . - , . ? ();

+4
3

, ; , - operator(), 1; , , , : , class.

Lambdas ( , ) 2 3. , , 70- class.

, , lambdas ++ , " ", , ; , . , , , (= ) , , ; , , , . , , , ( - , , ), . , - , , , ( "" ) " " ( "" ).


  • , , .
  • , , , , .
  • , , ; ++ 11 ++ 03, de-lambdifying code - - , "" , . , , , - , , . .
+8

,

. lambdas , , " ". , - ( , ++).

, , , " - " " - ". , , .

. , . , , , , , .

, . , , API, (, , , ). , , .

... , ? -, . std::function. , , , .

, ... . , .

Lambdas - , , , . , , , , . lambdas 90% , .

lambdas - , . , . , ..

, . , , operator(), , .


:

auto lambda = new[&]() { localVar = 1; };   // Can't do?

:

auto lambda = new auto([&]() { localVar = 1; });   // Can't do?
+5

, , , .

- , lambda

, ++ 14, init - :

// internalState is a bool
auto l = [internalState = true] {};

,

?

// Raw owning pointers are bad, don't do this
auto l1 = [rintptr = new int] {
    // rintptr is a captured pointer, with heap allocated data
    delete rintptr;
};

// Unique pointer is better in every way.
auto l2 = [uptr = std::make_unique<int>()] {
    // uptr is a captured heap allocated int too
};

, . . , RAII, .

, . , , .

- , , : :

auto l = []{
    // Execute what you need before returning the lambda
    // Setup objects to be captured here
    return []{};
}();

, lambda

std::function. .

std::function<void()> func;

{
    // The lambda is moved to func
    func = []{};
}

// func still holds it instance of the lambda.

, std::function . , SBO, , , .

trueOrFalse , ,

, . , , . , .

, , , else, . Capture private .

, . , .

()

:

auto overloaded = [](const auto& val) {
    std::cout << val << std::endl;
};

overloaded(4); // prints 4
overloaded(6.8); // prints 6.8
overloaded("test"); // prints test

, lambdas, :

// C++17 for simplicity
template<typename... Ls>
struct overload : Ls... {
    explicit overload(Ls... ls) noexcept : Ls{std::move(ls)}... {}

    using Ls::operator()...;
};

lambdas:

auto o = overload(
    []{},
    [i = 0](int) {},
    [&](double) {}
);

.

++ 14, overload .


, constexpr:

constexpr void foo() {
    []{}(); // Ill formed
}

struct MyFunctor {
    constexpr MyFunctor() = default;

    constexpr void operator()(){}
};

constexpr void bar() {
    MyFunctor{}(); // okay
}

, ++ 17. Lambdas constexpr.

, - , .

auto lambda = [](auto someVec) {
    using T = typename decltype(someVec)::value_type; // ugh...
};

++ 2a :

auto lambda = []<typename T>(std::vector<T> someVec) {
    // Yay! Only vectors and got T!
};
+1

Source: https://habr.com/ru/post/1684270/


All Articles