Pozytywna lambda: '+ [] {} ' - Co to za czary? [duplikat]

to pytanie ma już odpowiedź tutaj : rozwiązywanie wieloznacznych przeciążeń na wskaźniku funkcji i std:: funkcja dla lambda za pomocą + (1 ODPOWIEDŹ) Zamknięty 7 lat temu .

W pytaniu o przepełnienie stosu Redefiniowanie lambda niedozwolone w C++11, dlaczego?, podano mały program, który nie kompiluje:

int main() {
    auto test = []{};
    test = []{};
}

Na pytanie odpowiedziano i wszystko wydawało się w porządku. Następnie przyszedł Johannes Schaub i uczynił interesującą obserwację :

Jeśli umieścisz + przed pierwszą lambdą, magicznie zaczyna praca.

Więc jestem ciekaw: dlaczego poniższe działanie?

int main() {
    auto test = +[]{}; // Note the unary operator + before the lambda
    test = []{};
}

Kompiluje dobrze zarówno GCC 4.7+ i Clang 3.2+. Czy kod jest zgodny?

Author: Community, 2013-09-19

1 answers

Tak, kod jest zgodny ze standardem. + uruchamia konwersję do zwykłego starego wskaźnika funkcji dla lambda.

Co się dzieje to:

Kompilator widzi pierwszy lambda ([]{}) i generuje obiekt zamknięcia zgodnie z §5.1.2. Ponieważ lambda jest nie przechwytywaną lambda, stosuje się następujące zasady:

5.1.2 wyrażenia Lambda [expr.prim.lambda]

6 Typ zamknięcia dla lambda-wyrażenie BEZ lambda-capture ma publiczną nie-wirtualną, nie-jawną funkcję konwersji const do wskaźnika do funkcji o tym samym parametrze i typie zwrotu, co operator wywołania funkcji typu closure. Wartość zwracana przez tę funkcję konwersji jest adresem funkcji, która po wywołaniu ma taki sam efekt jak wywołanie operatora wywołania funkcji typu zamknięcia.

Jest to ważne, ponieważ operator jednoargumentowy + ma zestaw wbudowanych przeciążeń, w szczególności ten jeden:

13.6 wbudowane operatory [over.zbudowany]

8 dla każdego typu T istnieją kandydujące funkcje operatora postaci

    T* operator+(T*);

I z tym jest całkiem jasne, co się dzieje: gdy operator + Jest zastosowany do obiektu closure, zestaw przeciążonych wbudowanych kandydatów zawiera konwersję na dowolny wskaźnik, A Typ closure zawiera dokładnie jednego kandydata: konwersję na wskaźnik funkcji obiektu closure. lambda.

Typ test W auto test = +[]{}; jest zatem wydedukowany do void(*)(). Teraz druga linia jest łatwa: dla drugiego obiektu lambda/closure przypisanie do wskaźnika funkcji uruchamia taką samą konwersję jak w pierwszej linii. Mimo że drugi lambda ma inny typ zamknięcia, otrzymany wskaźnik funkcji jest oczywiście kompatybilny i może być przypisany.

 263
Author: Daniel Frey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55