Mieliśmy funkcję, która wykorzystywała wewnętrzną lambda, która nie przechwytuje, np .:
void foo() {
auto bar = [](int a, int b){ return a + b; }
// code using bar(x,y) a bunch of times
}
Teraz funkcjonalność zaimplementowana przez lambda stała się potrzebna gdzie indziej, więc zamierzam foo()
przenieść lambda z zakresu globalnego / przestrzeni nazw. Mogę zostawić go jako lambda, ustawiając opcję kopiuj-wklej lub zmienić na odpowiednią funkcję:
auto bar = [](int a, int b){ return a + b; } // option 1
int bar(int a, int b){ return a + b; } // option 2
void foo() {
// code using bar(x,y) a bunch of times
}
Zmiana tej funkcji na właściwą jest banalna, ale zastanawiałem się, czy istnieje jakiś powód, aby nie zostawiać jej jako lambda? Czy jest jakiś powód, aby nie używać wszędzie lambd zamiast „zwykłych” funkcji globalnych?
Odpowiedzi:
Jest jeden bardzo ważny powód, aby nie używać globalnych lambdas: ponieważ nie jest to normalne.
Regularna składnia funkcji C ++ istnieje już od czasów C. Programiści od dziesięcioleci wiedzą, co oznacza ta składnia i jak działają (choć wprawdzie cała ta funkcja rozkładania funkcji na wskaźnik czasami gryzie nawet doświadczonych programistów). Jeśli programista C ++ o dowolnym poziomie umiejętności wykraczającym poza „kompletny nowicjusz” widzi definicję funkcji, wie, co dostaje.
Globalna lambda to zupełnie inna bestia. Ma inne zachowanie niż zwykła funkcja. Lambdy są obiektami, podczas gdy funkcje nie. Mają typ, ale ten typ różni się od rodzaju ich funkcji. I tak dalej.
Więc teraz podniosłeś poprzeczkę w komunikacji z innymi programistami. Programista C ++ musi zrozumieć lambdas, jeśli chce zrozumieć, co robi ta funkcja. I tak, to jest rok 2019, więc porządny programista C ++ powinien mieć pojęcie, jak wygląda lambda. Ale wciąż jest to wyższy pasek.
I nawet jeśli to zrozumieją, pytanie w umyśle tego programisty brzmi ... dlaczego pisarz tego kodu napisał to w ten sposób? A jeśli nie masz dobrej odpowiedzi na to pytanie (na przykład, ponieważ wyraźnie chcesz zabronić przeciążania, jak w punktach dostosowywania Ranges), powinieneś użyć wspólnego mechanizmu.
W razie potrzeby preferuj oczekiwane rozwiązania od nowatorskich. Skorzystaj z najmniej skomplikowanej metody zdobycia punktu.
źródło
Mogę wymyślić kilka powodów, dla których chcesz uniknąć globalnych lambd jako zastępczych zastępców dla zwykłych funkcji:
„Dlaczego nie powinienem używać lambda zamiast stanowych funktorów (klas)?”
źródło
std::integral_constant
do tego ...Po zapytaniu pomyślałem o przyczynie, aby tego nie robić: ponieważ są to zmienne, są one podatne na statyczne zlecenie inicjalizacji Fiasco ( https://isocpp.org/wiki/faq/ctors#static-init-order ), które mogłyby powodować błędy w linii.
źródło
constexpr
lambdas ... prawdziwy punkt brzmi: Wystarczy użyć funkcji.Problem o pewnym poziomie złożoności wymaga rozwiązania o co najmniej tej samej złożoności. Ale jeśli istnieje mniej skomplikowane rozwiązanie tego samego problemu, wówczas naprawdę nie ma uzasadnienia dla korzystania z bardziej złożonego. Po co wprowadzać złożoność, której nie potrzebujesz?
Między lambda a funkcją funkcja jest po prostu mniej złożonym rodzajem bytu tych dwóch. Nie musisz uzasadniać, że nie używasz lambda. Musisz uzasadnić użycie jednego. Wyrażenie lambda wprowadza typ zamknięcia, który jest nienazwanym typem klasy ze wszystkimi zwykłymi specjalnymi funkcjami składowymi, operatorem wywołania funkcji oraz, w tym przypadku, niejawnym operatorem konwersji na wskaźnik funkcji i tworzy obiekt tego typu. Inicjowanie kopii zmiennej globalnej z wyrażenia lambda po prostu robi znacznie więcej niż tylko definiowanie funkcji. Definiuje typ klasy z sześcioma niejawnie zadeklarowanymi funkcjami, definiuje dwie dodatkowe funkcje operatora i tworzy obiekt. Kompilator musi zrobić znacznie więcej. Jeśli nie potrzebujesz żadnej z funkcji lambda, nie używaj lambda…
źródło
Lambda to funkcje anonimowe .
Jeśli używasz nazwanej lambda, oznacza to, że zasadniczo używasz nazwanej funkcji anonimowej. Aby uniknąć tego oksymoronu, równie dobrze możesz użyć funkcji.
źródło
Kiedyś używaliśmy funkcji zamiast globalnego funktora, więc łamie to spójność i zasadę najmniejszego zdziwienia .
Główne różnice to:
źródło