Soru Neden lambda ifadeleri gerektirmiyor, ancak işlevi var mı?


Bazı kod kullanımı lambda ifadesi gibi:

#include <vector>
#include <algorithm>
int main(){
    std::vector<int> vi={3,1};
    std::sort(vi.begin(),vi.end(),[](int x,int y){
        return x<y;
    });
    return 0;
}

Gerektirmeyen #include< functional> derlemek, ancak lambda işlevini depolamak için bir değişken kullanırsam:

#include <vector>
#include <algorithm>
#include <functional>
int main(){
    std::vector<int> vi={3,1};
    std::function<void()> compf=[](int x,int y){
        return x<y;
    };
    std::sort(vi.begin(),vi.end(),compf);
    return 0;
}

O zaman eklemem gerek <functional> derlemek, neden? Ve neden sort() ayrıca içermez <functional> zaten?


25
2017-09-06 04:23


Menşei


Bir lambda'nın std :: işlevi olduğu izlenimi altında mısınız? Değil; onu sakladığınızda bir dönüşüm var compf. - user2357112
Çünkü lambda ifadeleri dilin bir parçası. std::function standart kütüphanenin bir parçasıdır ve bir başlık gerektirir. - Paul Rooney
@PaulRooney, Adil olmak gerekirse, for (int i : {1, 2, 3}) Ayrıca açık standart kütüphane kullanımına rağmen bir başlık gerektirir. - chris
@chris true. Bunu her zaman biraz tuhaf buldum. - Paul Rooney


Cevaplar:


Çünkü bir lambda ifadesi, derleyici tarafından sağlanan bir çekirdek dil özelliğidir. std::function kodda uygulanan bir kütüphane özelliğidir. Lambda'yı bir değişkende saklamak için herhangi bir şey eklemeniz gerekmediğini unutmayın.

auto f = [](int x, int y){ return x < y; };

Sadece eklemeniz gerek <functional> eğer bir depoda saklamayı planlıyorsanız std::function (çünkü uygulandığı yerdir).

Bir lambda tipi bir izlenim altında görünüyorsun std::function. O değil. Her lambda ifadesinin kendine özgü, isimlendirilemez türü vardır. Yukarıdaki türden, auto. std::function depolayabilecek daha genel bir türüdür herhangi Uygun imzaya sahip işlev benzeri nesne. Örneğin, bir std::function<int(int,int)> nesne ve normal bir işlev, bir işlev nesnesi ve bir lambda atayın.

#include <functional>
int minus_func(int a, int b) { return a - b; }

struct plus_t {
    int operator()(int a, int b) const { return a + b; }
};

int main() {
    auto mult_lambda = [](int a, int b) { return a * b; };

    std::function<int(int,int)> func;
    func = minus_func;
    func = plus_t{};
    func = mult_lambda;
}

Ayrıca, bu genelliğe, dinamik ayırma ve dolaylılık biçiminde bir maliyet de vardır. Bir lambda'yı gerçek tipinin bir değişkeninden geçirirken, çoğu zaman belirtildiği gibi.


46
2017-09-06 04:26



std::function<> Uygulamalar, belirli bir boyutun altındaki geçiş tabloları için dinamik ayırmayı önlemek amacıyla statik depolamaya sahip olabilir. Bu küçük dizge optimizasyonuna benzer. - user2296177
Hat nasıl "Işlev = plus_t {}" çalışmak gerekiyordu? Anonim bir nesne oluşturur mu "Plus_t"? - blackpen
"Onu atama" yerine "onu atayın" mı demek istiyorsun? - Jesper Juhl
@blackpen: Evet, işte böyle. Tek tip başlatma sözdizimini kullanır. Daha geleneksel olanı da kullanabilirdim func = plus_t();. - Benjamin Lindley
@ user2296177 "Zorunlu" belirli nesneler için (işlev göstergeleri ve birkaç tane diğerleri) var, "olabilir" (genellikle belirli bir boyutun altında) nesneler için olabilir, ancak küçük lambdaların bir STD'de SOO ile saklanması gereken bir yetkisi yoktur: : işlev (bu, ancak kitaplık uygulama sorununun kalitesidir). Bir popüler std kütüphanesi (MSVC'ler) ikiden büyük olmayan herhangi bir çağrılabilir std::stringhaklı olarak hatırlarsam s (kısa dizeler için SOO var). - Yakk - Adam Nevraumont


lambda işlevleri herhangi bir kütüphaneden bağımsız olarak dilin bir parçasıdır.

std::functionÖte yandan, standart kütüphanenin bir parçasıdır ve standart kütüphane başlık dosyasında tanımlanmıştır functional.

Dolayısıyla, kullanımı

std::sort(vi.begin(),vi.end(),[](int x,int y){
    return x<y;
});

gerektirmez functional olmak #included kullanırken

std::function<void()> compf=[](int x,int y){
    return x<y;
};
std::sort(vi.begin(),vi.end(),compf);

gerektirir functional olmak #included.


6
2017-09-06 04:28