Miałem wrażenie, że typ lambda to wskaźnik funkcji. Kiedy wykonałem następujący test, stwierdziłem, że jest źle ( demo ).
#define LAMBDA [] (int i) -> long { return 0; }
int main ()
{
long (*pFptr)(int) = LAMBDA; // ok
auto pAuto = LAMBDA; // ok
assert(typeid(pFptr) == typeid(pAuto)); // assertion fails !
}
Czy w powyższym kodzie brakuje jakiegoś punktu? Jeśli nie, to jakie jest typeof
wyrażenie lambda po wydedukowaniu za pomocą auto
słowa kluczowego?
Odpowiedzi:
Typ wyrażenia lambda jest nieokreślony.
Ale generalnie są one tylko cukrem syntaktycznym dla funktorów. Lambda jest tłumaczona bezpośrednio na funktor. Wszystko w środku
[]
jest zamieniane na parametry konstruktora i składowe obiektu funktora, a parametry wewnątrz()
są zamieniane na parametry dla funktoraoperator()
.Lambda, która nie przechwytuje żadnych zmiennych (nic wewnątrz
[]
's), może zostać przekonwertowana na wskaźnik funkcji (MSVC2010 nie obsługuje tego, jeśli jest to twój kompilator, ale ta konwersja jest częścią standardu).Ale rzeczywisty typ lambda nie jest wskaźnikiem funkcji. To jakiś nieokreślony typ funktora.
źródło
operator()
zasadzie stackoverflow.com/questions/356950/c-functors-and-their-usesJest to unikalna nienazwana struktura, która przeciąża operator wywołania funkcji. Każde wystąpienie lambda wprowadza nowy typ.
W szczególnym przypadku lambdy nieprzechwytywanej struktura dodatkowo ma niejawną konwersję na wskaźnik funkcji.
źródło
type_info::name()
jest zdefiniowany w implementacji, więc może zwrócić wszystko. W praktyce kompilator nada typowi nazwę na potrzeby konsolidatora.Klauzula zawiera listę różnych właściwości tego typu. Oto kilka najważniejszych informacji:
Konsekwencją tego ostatniego fragmentu jest to, że gdybyś użył konwersji, byłbyś w stanie przypisać
LAMBDA
dopFptr
.źródło
Typy funkcji są rzeczywiście takie same, ale lambda wprowadza nowy typ (jak funktor).
źródło
__PRETTY_FUNCTION__
, jak wtemplate<class T> const char* pretty(T && t) { return __PRETTY_FUNCTION__; }
, i zdejmuję dodatkowe, jeśli zacznie się robić tłoczno. Wolę zobaczyć kroki pokazane w zastępowaniu szablonów. Jeśli brakuje__PRETTY_FUNCTION__
, są alternatywy dla MSVC itp., Ale wyniki są zawsze zależne od kompilatora z tego samego powodu, dla którego CXXABI jest konieczny.Należy również zauważyć, że lambda można zamienić na wskaźnik funkcji. Jednak typeid <> zwraca obiekt inny niż trvial, który powinien różnić się od lambda do ogólnego wskaźnika funkcji. Zatem test dla typeid <> nie jest prawidłowym założeniem. Ogólnie C ++ 11 nie chce, abyśmy martwili się o specyfikację typu, wszystko to ma znaczenie, jeśli dany typ można zamienić na typ docelowy.
źródło
Praktyczne rozwiązanie z Jak mogę przechowywać obiekt boost :: bind jako element członkowski klasy? , spróbuj
boost::function<void(int)>
lubstd::function<void(int)>
.źródło