2012-07-10 8 views
6

Aşağıdaki kodu düşünün: yakalamaları ile biri başarısız olurken Clang 3.1 ile derlenenLambda yakalama, uyumsuz işlenen türlerinin hata neden olur?

main() 
{ 
    bool t; 
    ... 
    std::function<bool (bool)> f = t ? [](bool b) { return b; } : [](bool b) { return !b; }; // OK 
    std::function<bool (bool)> f = t ? [t](bool b) { return t == b; } : [t](bool b) { return t != b; }; // error 
} 

olmayan yakalama lambda atama çalışır:

main.cpp:12:36: error: incompatible operand types ('<lambda at main.cpp:12:38>' and '<lambda at main.cpp:12:71>') 
     std::function<bool (bool)> f2 = t ? [t](bool b) { return t == b; } : [t](bool b) { return t != b; }; // error 
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

yakalayan aynı değişken neden olur mu Neden Uyumsuz türlerde 2 lambdas?

cevap

12

Bir lambda türü, "kapanış türü" adı verilen "benzersiz, birleşik olmayan sınıf türü" dir. Her lambda, fonksiyon gövdesini çağırmak için aşırı yüklenmiş bir operatöre() sahip olan deklarasyon kapsamına yerel olarak farklı bir tip olarak uygulanır. Bunu yazarsanız:

Örnek

class unique_lambda_name_1 
{ 
bool t; 
public: 
unique_lambda_name_1(bool t_) t(_t) {} 
bool operator() (bool b) const { return t==b; } 
} a(t); 
class unique_lambda_name_2 
{ 
bool t; 
public: 
unique_lambda_name_2(bool t_) t(_t) {} 
bool operator() (bool b) const { return t!=b; } 
} b(t); 

a ve b farklı türleri vardır ve kullanılamaz:

auto a=[t](bool b){return t==b;}; 
auto b=[t](bool b){return t!=b;}; 

Sonra derleyici bu (daha fazla veya daha az) derler ?: operatöründe. Bununla birlikte, §5.1.2 (6), yakalanmayan bir lambda'nın kapama tipinin, lambda'yı bir fonksiyon göstergesine dönüştüren, açık olmayan, kamusal bir dönüşüm operatörüne sahip olduğunu belirtir - kapanma yapılamaz basit işlevler olarak. Aynı argüman ve geri dönüş türlerine sahip herhangi bir lambda, aynı tipte bir işaretçiye dönüştürülebilir ve böylece üçlü?: Operatörü bunlara uygulanabilir.

Örnek: olmayan yakalama lambda

auto c=[](bool b){return b;}; 

bu gibi uygulanır:

auto x = t?[](bool b){return b;}:[](bool b){return !b;}; 

aslında bu şu anlama gelir:

class unique_lambda_name_3 
{ 
static bool body(bool b) { return b; } 
public: 
bool operator() (bool b) const { return body(b); } 
operator decltype(&body)() const { return &body; } 
} c; 

bu hat anlamına gelmektedir:

// a typedef to make this more readable 
typedef bool (*pfun_t)(bool); 
pfun_t x = t?((pfun_t)[](bool b){return b;}):(pfun_t)([](bool b){return !b;}); 
+0

Detaylı açıklama için teşekkürler. Farklı şekilde uygulandıklarını bilmiyordum. Şimdi mantıklı. –