2015-10-12 20 views
9

Soruma göre statik üye başlatıcıları için lambda kapsamı.Statik üyeler için lambda kapsamı başlatıcı

#include <functional> 
#include <iostream> 

struct S { 
    static const std::function<void(void)> s_func; 
}; 

const std::function<void(void)> S::s_func = []() { 
    std::cout << "Hello from " << __PRETTY_FUNCTION__ << std::endl; 
}; 

int main(void) { 
    S::s_func(); 
    return 0; 
} 

4,8 başlayarak GCC S kapsamındaki lambda tanımlar, böylece programın böyle bir şey verir:

Hello from S::<lambda()> 

(gcc-4.8.2 farklı bir tanım, aşağıdaki de dikkate almak __FUNCTION__ & Co makroları için, ama yine de lamda yine) S içinde

arada gcc-4.7 genel kapsamda lambda tanımlar

, böylece program çıkışları

0 tanımlanır
Hello from <lambda()> 

Muhtemelen daha yeni gcc daha uyumludur. Ancak standardın aslında bu yönü belirleyip belirlemediğini ya da uygulamaya bağlı olabileceğini sormak istiyorum.

Güncelleme: @ user5434961 gibi tüm __FUNCTION__ -alike makro uygulama bağımlı olduğunu ileri sürdü, bu yüzden bir standart uyumlu testinde bunları önlemek için daha iyidir. ama ilgili hata raporu bulamıyorum önce

#include <functional> 
#include <iostream> 

struct S { 
    static const std::function<void(void)> s_func; 
private: 
    static const int s_field; 
}; 

const std::function<void(void)> S::s_func = []() { 
    std::cout << "Hello from S::s_func. S::s_field = " << S::s_field << std::endl; 
}; 

const int S::s_field = 1; 

int main(void) { 
    S::s_func(); 
    return 0; 
} 
+0

Güncellenmiş örnekte 'S :: s_field' i' s_field' olarak değiştirmelisiniz? Aksi takdirde, kapsam her ne olursa olsun derler. – Lingxi

+0

"S :: s_field" özel olduğu için, global kapsamdan erişilemez, bu nedenle kod gerçekten GCC-4.7'deki derlemeyi bozar. – user3159253

+0

Evet, evet. Özel olanı gözden kaçırdım. – Lingxi

cevap

7

Bu sorun gündeme gelmiştir: Yani burada bir derleyici S kapsamında bu tür lambdas tanımlar ve aksi derleme bozulursa derlenebilir örnektir. İşte bir dosyaya verildiği iddia edilen bir MSVC hata raporu için bir broken link. (Hala 2015'te sabitlenmemiş: rise4fun'da test edebilirsiniz). Ancak GCC için 4.7 ve 4.8 arasında bir yerde sabitlenmiştir. bir hata olarak yedeklemek için kullanılan ilgili standardese olup:

[C++ 11, 9.4.2/2] static veri üyesi tanımını uzun içinde başlatıcı sentezleme sınıfının kapsamında olup, .

[C++ 11, 5.1.2/2] Bir lambda ifadesinin değerlendirilmesi, geçici bir prvalue (12.2) ile sonuçlanır. Bu geçici kapatma nesnesi denir. Bir lambda ifadesi, değerlendirilmemiş bir işlenende görünmeyecektir (Madde 5).

[C++ 11/3 5.1.2], benzersiz, isimsiz kaynaşmama sınıf tipi (aynı zamanda kapak nesnenin tipidir) lambda ekspresyon türü - kapama adı türü - özellikleri aşağıda açıklanmıştır. Bu sınıf türü bir toplam değil (8.5.1). Kapanış türü, 'un karşılık gelen lambda ifadesini içerdiği en küçük blok kapsamı, sınıf kapsamı veya ad alanı kapsamında bildirilmiştir.

Daha önce

Why lambda in static initializer can't access private members of class in VC++2013?

C++11 lambdas can access my private members. Why?

Why is it not possible to use private method in a lambda?

4

Ben sınıf kapsamında olmalıyım.cppreference Alıntı (vurgu benim):

lambda ifade ADL amaçları için bildirilen isimsiz prvalue geçici bir nesne kapak türü olarak bilinen benzersiz bir isimsiz kaynaşmama olmayan agrega tipte , (yapıları kapsamı, sınıf kapsamı veya lambda ifadesi'u içeren en küçük blokta . S::s_func üzerinden-of-line tanımda

, size zaman S:: karşılaşıldığında S kapsamına girer. Yani, lambda ifadesi S sınıf kapsamında yer almaktadır. Daha yakın tip S'un bir üyesi olduğu için, S'un özel üyelerine erişim verilir.

+0

Eşit derecede yardımcı yanıtlar için hem siz hem de @ user5434961'e teşekkür ederiz. Cevabını, sizinkilerden biraz önce olduğu için kabul edildi olarak işaretledim. – user3159253

+0

@ user3159253 Rica ederim :) user5434961'in cevabı standart belgeyi gerekçe gösterdiğinden daha iyi. – Lingxi

İlgili konular