Captureless lambda'nın standart tarafından boş olması garanti ediliyor mu?


12

Bir şablon fonksiyonundaki diğer lambdaslardan boş (kaptasız) lambdasları tanımlamanın bir yolunu arıyorum. Şu anda C ++ 17 kullanıyorum ama C ++ 20 cevaplarını da merak ediyorum.

Kodum şöyle görünüyor:

template<typename T>
auto func(T lambda) {
    // The aguments of the lambdas are unknown

    if constexpr (/* is captureless */) {
        // do stuff
    }
}

C ++ standardı (17 veya 20) tarafından, bir fonksiyon göstergesine dönüştürülebilen, yakalanmamış bir lambda'nın da std::is_emptyverimi doğrulayacağı garanti ediliyor mu?

Bu kodu örnek olarak alalım:

auto a = []{}; // captureless
auto b = [c = 'z']{}; // has captures

static_assert(sizeof(a) == sizeof(b)); // Both are the same size
static_assert(!std::is_empty_v<decltype(b)>); // It has a `c` member
static_assert(std::is_empty_v<decltype(a)>); // Passes. It is guaranteed?

Canlı örnek


2
Yalnızca şablon olmayan lambdaslarla ilgileniyorsanız, bir işlev işaretçisine ( +lambda) dönüştürmenin iyi biçimlendirilmiş olup olmadığını kontrol etmek için SFINAE kullanabilirsiniz .
HolyBlackCat

@HolyBlackCat Bunu düşündüm, ancak hatırladığım kadarıyla, MSVC, dönüşüm operatörünü aşırı yükledikleri için buna izin vermiyor.
Guillaume Racicot

@GuillaumeRacicot MS, kullanılabilir tüm arama kuralları için ayrı bir dönüşüm operatörü sunar. Sadece birini seçin ve lambda'yı karşılaştırılabilir bir fonksiyon işaretçisine dönüştürmeye çalışın ve başarılı olup olmadığını kontrol edin.
Remy Lebeau

+burada çalışıyor gibi görünüyor .
HolyBlackCat

Yanıtlar:


13

Hayır, aslında standart, lambdaların beyanlarıyla uyuşmayan bir boyuta sahip olmalarına açıkça izin vermektedir. [expr.prim.lambda.closure] / 2 eyalet

Kapatma türü, karşılık gelen lambda ifadesini içeren en küçük blok kapsamı, sınıf kapsamı veya ad alanı kapsamı içinde bildirilir. [Not: Bu, kapatma türüyle ([basic.lookup.argdep]) ilişkili ad alanları ve sınıflar kümesini belirler. Lambda bildiricisinin parametre türleri bu ilişkili ad alanlarını ve sınıflarını etkilemez. - son not] Kapatma türü toplu bir tür değil. Bir uygulama, programın değiştirilebilecek gözlemlenebilir davranışını değiştirmemesi koşuluyla, kapatma türünü aşağıda açıklanandan farklı olarak tanımlayabilir:

  • kapatma tipinin boyutu ve / veya hizalanması,

  • kapatma türünün önemsiz şekilde kopyalanıp kopyalanamayacağı ([class.prop]) veya (2.3)

  • kapatma türünün standart mizanpaj sınıfı ([class.prop]) olup olmadığı.

Bir uygulama, kapatma türüne rvalue referans türü üyeleri eklemez.

benimkini vurgula

Bu da uygulamanın lambdaya yakalama olmasa bile bir üye vermesini sağlar. Hiçbir uygulamanın yapamayacağını düşünmüyorum, ancak yasal olarak bunu yapmasına izin veriliyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.