Yanıtlar:
Bireysel lambdalar derleyici tarafından farklı sınıflara çevrilir. Örneğin, lambda1'in tanımı şuna eşittir:
class SomeCompilerGeneratedTypeName {
public:
SomeCompilerGeneratedTypeName(...) { // Capture all the required variables here
}
void operator()(T& arg) const {
// ...
}
private:
// All the captured variables here ...
};
Bu nedenle, derleyici tarafından iki farklı tür oluşturulur; auto lambda = condition ? lambda1 : lambda2;
Aşağıdakiler işe yarar:
auto lambda = condition ? std::function<void(T&)>(lambda1) : std::function<void(T&)>(lambda2);
Her iki lambdanın gerçekten farklı türler olduğunu vurgulamak <typeinfo>
için standart kütüphaneden ve typeid
operatörden kullanabiliriz. Lambdalar polimorfik tipler değildir, bu nedenle standart 'tipid' operatörünün derleme zamanında değerlendirilmesini garanti eder. Bu, RTTI devre dışı olsa bile aşağıdaki örneğin geçerli olduğunu gösterir:
#include <iostream>
#include <typeinfo>
int main()
{
struct T {
};
auto lambda1 = [&](T& arg) {
return;
};
auto lambda2 = [&](T& arg) {
return;
};
std::cout << typeid(lambda1).name() << "/" << typeid(lambda1).hash_code() << std::endl;
std::cout << typeid(lambda2).name() << "/" << typeid(lambda2).hash_code() << std::endl;
return 0;
}
Programın çıktısı (GCC 8.3 ile, bkz. Gobolt ):
Z4mainEUlRZ4mainE1TE_/7654536205164302515
Z4mainEUlRZ4mainE1TE0_/10614161759544824066
SomeCompilerGeneratedTypeName1
veSomeCompilerGeneratedTypeName2
İlginçtir ki, lambdalar yakalamadan uzaksa, operatör +
hilesi kullanılabilir:
auto lambda1 = [](int arg) { ... };
auto lambda2 = [](int arg) { ... };
auto lambda = condition ? +lambda1 : +lambda2; // This compiles!
lambda(2019);
Bu çalışır, çünkü +
lambda'yı bir işlev işaretçisine dönüştürür ve her iki işlev işaretçisi de aynı türe sahiptir (gibi bir şey void (*)(int)
).
GCC ve Clang ile (ancak MSVC ile değil) +
atlanabilir, lambdalar hala fonksiyon işaretçilerine dönüştürülecektir.
Derleyici ne tür auto
olması gerektiğine karar veremez :
auto lambda = condition ? lambda1 : lambda2;
çünkü her lambda farklı ve benzersiz bir türe sahiptir.
Çalışmanın bir yolu:
auto lambda = [&](T& arg) {
return (condition ? lambda1(arg) : lambda2(arg));
}
Derleme yapmaz, çünkü her lambda'nın benzersiz bir türü vardır, ortak bir türü yoktur ?:
.
Bunları içine alabilirsin std::function<void(T&)>
, ör.
auto lamba1 = [&](T& arg) {
...
};
auto lambda2 = [&](T& arg) {
...
};
auto lambda = condition ? std::function(lambda1) : lambda2; // C++17 class template deduction