C++11 und das fehlen von polymorphen Lambda-Ausdrücke - warum?
Ich habe die überprüfung der version der C++11 standard. Insbesondere den Abschnitt über lambdas, und ich bin verwirrt, als die Argumentation für die nicht-Einführung der polymorphe Lambda-Ausdrücke.
Beispielsweise unter den 100001 Möglichkeiten der polymorphe Lambda-Ausdrücke verwendet werden könnten, hatte ich gehofft, wir könnten, verwenden Sie code wie den folgenden:
template<typename Container>
void foo(Container c)
{
for_each(c.begin(), c.end(), [](T& t) { ++t; });
}
Was waren die Gründe:
-
War es, als der Ausschuss lief die Zeit davon?
-
Dass der polymorphe Lambda-Ausdrücke sind zu schwer zu implementieren?
-
Oder vielleicht, dass Sie gesehen werden, nicht als erforderlich durch den PTB?
Hinweis: Bitte denken Sie daran, das Beispiel oben ist nicht der einzige, und es ist nur als eine Anleitung, um die Arten von code. Antworten, die sich ausschließlich konzentrieren auf die Bereitstellung eines workaround für das obige Stück code nicht als gültig angesehen werden!
Verwandte Quellen:
- Lambda-Ausdrücken und closures für C++ (Aktenzeichen N1968=06-0038)
- Kann die lambda-Funktionen werden Vorlagen?
- verdammt, was für ein Durcheinander syntax.
- was ist falsch an der syntax? es ist eigentlich ganz nett.
- Ich bin damit einverstanden. Obwohl, jeder der drei Sätze von Klammern gibt es eigentlich für einen Grund: der erste (
[]
) enthält die Liste der Variablen zu schließen, über-und/oder welche nicht zu schließen, sowie, wie, Sie zu fangen (by-reference oder by-value), der zweite (()
) enthält der parameter Liste, der Dritte ({}
) enthält der Körper. Aber, zum Beispiel, so etwas wieλt → ++t
(wie in Haskell) statt[](T& t) { ++t; }
wäre viel schöner. - Der Begriff ist nicht "in der Nähe über" man nennt Sie die capture-Liste. Im wesentlichen die Fähigkeit zum erfassen von Variablen, die entweder Referenz oder Kopie vom umschließenden Rahmen, zur Verwendung in lambda. - Ich persönlich denke, die syntax ist ganz nett.
- Das ist, was "in der Nähe über" bedeutet. en.wikipedia.org/wiki/Closure_(computer_programming)
- Jörg: ich weiß nicht bestreiten, dass jedes dieser Zeichen hat einen Grund - ich denke, es ist nur bloaty, aber das ist wahrscheinlich verursacht durch die Tatsache, dass er versucht zu patchen eines schon von Motten geritten Kleid, das war nicht gut, mit zu beginnen.
- Naja, normalerweise sagt man "in der Nähe über die Umwelt". Die meisten Sprachen erlauben nicht, Sie explizit anzugeben, welche Teile der Umgebung und wie "nahe vorbei", Sie immer in der Nähe, über die ganze Umgebung, so gibt es keine vollständig etablierte Begriff für das, was tho es nennen, wenn Sie "erledigt" oder "erfassen" die einzelnen Variablen im Gegensatz zu der gesamten Umgebung.
- Ich hasse den C++0x-die lambda-syntax auch, aber die syntax ist zumindest im Einklang mit dem Stil von C/C++. Haskell der lambda ist viel schöner, aber es sähe eher seltsam.
- Es wäre ein Interessantes experiment, zu entfernen alles, die entlassen worden ist durch spätere Erweiterungen (z.B. entfernen Sie alle Formen der Initialisierung außer der uniform initialization syntax), damit die abstrakte syntax für die nicht-redundante Untermenge von C++ identisch zu dem, was es heute ist, aber design ist eine neue konkrete syntax mehr entlang der Linien von Scala und/oder Cobra und/oder Ruby (je nachdem, ob Sie lieber Klammern, Einrückungen oder keywords). Ich Wette, Sie können einige ziemlich gut aussehende Sprache, die zu 100% isomorph zu C++.
- Die Sache über die C++ - syntax für Lambda-Ausdrücke ist, dass es so ziemlich unvermeidlich. In einem GC ' ed Sprache, die Sie bekommen können Weg mit einem normalen Verschluss, der einfach fängt alles von Referenz. In C++, Sie ziemlich viel müssen in der Lage sein, um anzugeben, ob eine variable erfasst werden soll, per Referenz oder Wert. Wenn es nicht für diese Anforderung, die
[]
's könnte leicht beseitigt werden. - Ich scheine zu erinnern, dass litb einmal erwähnt, dass die lambdas wurden monomorphe, da Sie sonst nicht spielen schön mit Konzepten. (das scheint wie ein erstaunlich dummes argument, und ist nur mit zusätzlichen ironisch jetzt, dass Konzepte wurden fallen gelassen) Vielleicht kann er uns aufklären über die details, wenn er Sie sieht diese Frage allerdings.
- nun, die, die du verlinkt hast Kann lambda-Funktionen werden Vorlagen?, was ist Ihre Frage hinzufügen, was nicht schon dort beantwortet?
- Meh. Ich kann auch ohne Leben.
[](decltype(*begin) t) { ++t; }
- nun, die Konzepte wurden fallen gelassen, kann es sein, dass Sie nicht hinzufügen, Vorlage lambdas, denn Sie wollen sein in der Lage, die Konzepte wieder in der Sprache der nächsten Zeit um.
- Es sind genau 33 Möglichkeiten der polymorphe Lambda-Ausdrücke können verwendet werden?
- vielleicht. (Oder nur, dass Sie fiel Konzepte, um Zeit zu sparen, und so wäre es albern, zu verbringen die zusätzliche Zeit, re-hinzufügen von features wie dieses, sobald Begriffe waren), Aber es scheint mir, dass die Vorstellung von Konzepten wird verkrüppelt, wenn es kann nicht Ausdrücken, der polymorphe Lambda-Ausdrücke. Vielleicht sollten Sie stattdessen konzentrierten sich auf die kommenden up mit mehr expressiven Konzepten. Wie es scheint, Sie waren einfach zu vernarrt in Konzepte und nicht bereit zu sehen, dass, wenn es nicht auszudrücken beliebten Funktionen der Sprache, dann ist es nicht das beliebte feature, das repariert werden muss, aber die Konzepte Spezifikation.
- dann wieder, dieser basiert auf einem halb vergessenen Kommentar/Antwort von litb ich auf zu Lesen, SO Monaten. So nehmen Sie es für was es Wert ist. 😉
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den Grund haben wir nicht, der polymorphe Lambda-Ausdrücke erklärt ziemlich gut in dieses posting.
Es hat zu tun mit den Begriffen Funktion, die gezogen wurde von C++11: im wesentlichen, der polymorphe Lambda-Ausdrücke sind die gewöhnlichen, ohne die Funktion Vorlagen und wir wussten nicht, wie typecheck ein Konzept-eingeschränkte-Vorlage, die verwendet eine unbegrenzte Vorlage. Jedoch, die Lösung, das problem stellt sich einfach heraus, wie gezeigt, hier(Toter link), so dass ich glaube nicht, dass es irgendein Hindernis übrig.
Den link zu cpp-next ist tot; die relevanten Informationen gefunden werden können hier
Da das argument,
c
erfüllt die STL Anforderungen für einen container, Sie sollten in der Lage sein, etwas zu verwenden, wieWerde ich auch präsentieren John Purdy ' s Kommentar oben, das ist ein weiterer Weg, um die typename-Sie wollen in dieser lambda:
(Ja, Dominar, ich weiß nicht, wie Sie diese Antwort, denn es beantwortet nicht deine Frage, aber ich bin bereit zu Wetten, dass die nächste person, die kommt, diese Frage werde auf der Suche nach einem Weg, um Ihren code zu arbeiten, so macht es Sinn, einige Techniken um, wo die Frage relevant ist.)
Ist es wahrscheinlich, weil es bereits eine syntax, um dies zu tun, und der Zweck des lambdas ist die Einführung eines wesentlich einfacheren syntax ist es, das deckt die meisten Fälle. Wenn Sie versuchen, auf alle Fälle (was passiert, wenn Sie wollten, dass die automatisch generierten Funktor Erben zu einer bestimmten Basis-Klasse?), Sie verlieren die komparativen Vorteile (Einfachheit und frische) der lambda.
Ich weiß wirklich nicht, wie die vorgeschlagenen syntax. Ist
T
einem keyword? Tun alle Bezeichner für die Namen-lookup erhalten, schaltet sich automatisch in template typename Argumente? Verhindert, dass Sie vom erkennen von Rechtschreibfehlern, die IMO ist eine BAD Idee:Es führt auch action-at-a-Distanz Verhalten, wenn die namens Art eingeführt, die in einigen header-Datei irgendwo, die Bedeutung ändert sich plötzlich. Auch wirklich SCHLECHT.
Gut, da es eigentlich um eine Vorlage zu erstellen, wir leihen könnte, die bestehende syntax:
Dies ist eindeutig und erlaubt nun die nicht-Typ template-Argumente (hilfreich für das annehmen von arrays durch Verweis), aber ist wirklich unhandlich. An diesem Punkt sind Sie besser schreiben, aus dem Funktor von der hand, es wird sein viel einfacher zu verstehen.
Allerdings denke ich, dass eine einfache syntax möglich ist, mit der
auto
Stichwort:Nächsten Abschnitt wird fälschlicherweise davon ausgegangen, dass die template-parameter erscheint auf dem Funktor geben, anstatt seine
operator()()
:Aber jetzt haben Sie ein problem, dass
for_each
folgert ein typename template-argument, nicht ein template template argument. Typ-Inferenz ist nicht möglich in diesem Kontext.In der aktuelle Vorschlag lambdas Typ, auch wenn es eine unsägliche (andere als
decltype
) geben. Man müsste zu verlieren, dass die Funktion, um die Ableitung an der call-site.Beispiel zeigt, dass das Problem NICHT ein Mangel lambdas, es ist einfach eine nicht ableitbar Kontext:
Den template-parameter type
std::min
muss explizit angegeben werden. Lambda-Ausdrücke sind nicht anders aus vorhandenen funktoren in dieser Hinsicht.EDIT: Ok, jetzt, dass ich merke, wir sind nicht darauf hindeutet, dass der lambda-Ausdruck generiert ein template-Funktor geben, aber ein einziger nicht-template-Funktor geben, die sich um eine Vorlagen-Funktion Programm-Betreiber (
operator()()
), ich bin damit einverstanden, dass der compiler sollte in der Lage sein zu generieren ist so eine Sache. Ich schlage vor, dass Sie mit derauto
Stichwort wäre hier eine gute einfache syntax für die Anforderung, dass.Allerdings bin ich nicht wirklich glücklich mit
auto
entweder. Was Sie über lambdas mit mehreren Parametern:Ok, das funktioniert gut genug, aber was, wenn wir wollten zwei Parameter, sondern nur eine Art argument:
Scheint ok, aber ich finde die syntax irreführend. Die syntax legt nahe, dass der type-parameter ist eine Schlussfolgerung aus der ersten tatsächlichen parameter und der zweite parameter ist gezwungen, die gleiche Art, aber eigentlich sind die beiden aktuellen Parameter werden als gleich angesehen, während Typ-Inferenz.
Vielleicht ist es am besten, dass in diesem Fall begrenzt auf eine lambda-parameter pro Typ-argument, und wenn Sie möchten, etwas mehr eingeschränkt, schreiben die Funktor selbst. Dies scheint mir ein guter Kompromiss zwischen Flexibilität und power vs halten die syntax einfach.
(auto& t)
syntax nicht wirklich arbeiten, aber Sie denken, dass der C++ standards committee gemacht haben sollte es funktionieren, weil es fängt diese wirklich sinnvolle Nutzung ohne die lambda-syntax immer zu schlecht.auto
zeigt, dass wir uns nicht zu opfern, einfache syntax, aber dann geh ich zu behaupten, wir würden zu opfern, Funktion Argumente mit Art (aktuell können Sie ein template-argument, das selbst eine Vorlage, aber man kann nicht ein argument der Funktion, der Art, Sie haben einen konkreten Typ durch Angabe eines template-parameter-Liste die template-template-argument). Und meine Finger sind müde von der Eingabe des Wortes "Vorlage".template <typename T> using id = T;
dann kann man[](auto& x, std::id<x>& y)
zu stoppen Abzug. Ich denke, dass es noch lebensfähig ist, braucht einfach mehr utility-Funktionen. Roger Pate und ich diskutierte eine Weile, bevor er Sie verließ. Mit der neuen Sprache, Sie könnte tatsächlich loszuwerden explizite template-syntax, und nutzen Sie einfachauto
im parameter Typ. (Jede Funktion, die das getan haben, hatten eine implizitetemplate <typename __...>
.) Würde es vereinfachen Vorlagen erheblich.std::id<decltype(x)>
? Immer hässlich, aber vielleicht notwendig. Und ich glaube nicht, dassauto
ersetzen könnte expliziten template-notation im Allgemeinen Fall, aber es wäre sicher ein nettes Kürzel zu vereinfachen, schreiben einen erheblichen Teil der template-Funktionen.<typename T>[](T& x, T& y){x++; y--;}
Gut, dass du nun verlinkt hast n1968, die Antwort auf Ihre Frage offensichtlich. Sie finden es im Abschnitt 5.1 der Vorschlag.
Den folgende (Ihr Kommentar auf meine andere Antwort weiter oben) funktioniert:
Aber das folgende nicht:
Wahrscheinlich die C++ - Komitee sah lambdas als ähnlich zu dem zweiten Beispiel, als die erste. (Allerdings habe ich nicht herausgefunden, clevere Art und Weise zu definieren, die einen lambda-Ausdruck, in denen diese würde einen Unterschied machen. Wer irgendwelche verrückten Ideen?)
operator()
würde werden Vorlagen eher als der Funktor geben. Ja, ich denke, das könnte funktionieren.<int>
Teil auf seine eigene, und es muss Ihnen mitteilen, dass Teil. (Also, zu definieren, die eine vergleichbare lambda-Sie würde tun müssen, was ich in meinem erste Antwort)operator()()
.