Ist es möglich, durch konstante Referenz in einem Lambda-Ausdruck zu erfassen?
Ich möchte, dass die unten markierte Zuweisung fehlschlägt, zum Beispiel:
#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string strings[] =
{
"hello",
"world"
};
static const size_t num_strings = sizeof(strings)/sizeof(strings[0]);
string best_string = "foo";
for_each( &strings[0], &strings[num_strings], [&best_string](const string& s)
{
best_string = s; // this should fail
}
);
return 0;
}
Update: Da dies eine alte Frage ist, kann es hilfreich sein, sie zu aktualisieren, wenn in C ++ 14 Funktionen vorhanden sind, die Ihnen dabei helfen. Ermöglichen die Erweiterungen in C ++ 14 das Erfassen eines Nicht-Const-Objekts als Const-Referenz? ( August 2015 )
[&, &best_string](string const s) { ...}
?Antworten:
const
ist nicht in der Grammatik für Captures ab n3092:Der Text erwähnt nur Capture-by-Copy und Capture-by-Reference und erwähnt keinerlei Konstanz.
Fühlt sich für mich wie ein Versehen an, aber ich habe den Standardisierungsprozess nicht sehr genau verfolgt.
quelle
const
. Oder genauer gesagt, wenn die Erfassungsvariableconst
wäre, hätte der Compiler dem Programmierer das richtige Verhalten aufgezwungen. Es wäre schön, wenn die Syntax unterstützt würde[&mutableVar, const &constVar]
.a
wieconst
erklären ,const auto &b = a;
bevor das Lambda - und Captureb
[&foo = this->foo]
Innerhalb einerconst
Funktion wird eine Fehlermeldung angezeigt, die besagt, dass die Erfassung selbst Qualifizierer verwirft. Dies könnte jedoch ein Fehler in GCC 5.1 sein, nehme ich an.Im c ++ 14mit
static_cast
/const_cast
:DEMO
Im c ++ 17mit
std::as_const
:DEMO 2
quelle
const_cast
kann ein flüchtiges Objekt bedingungslos in ein const-Objekt ändern (wenn es zum Umwandeln aufgefordert wirdconst
), um Einschränkungen hinzuzufügen, die ich bevorzugestatic_cast
static_cast
um Konstante Referenz kann stillschweigend eine temporäre erstellen, wenn Sie den Typ nicht genau richtig bekommen&basic_string = std::as_const(best_string)
sollte alle Probleme lösenconst& best_string
.Ich denke, der Erfassungsteil sollte nicht angeben
const
, da die Erfassung bedeutet, dass er nur eine Möglichkeit benötigt, auf die äußere Bereichsvariable zuzugreifen.Der Bezeichner wird im äußeren Bereich besser angegeben.
Die Lambda-Funktion ist const (kann den Wert in ihrem Bereich nicht ändern). Wenn Sie also eine Variable nach Wert erfassen, kann die Variable nicht geändert werden, aber die Referenz befindet sich nicht im Lambda-Bereich.
quelle
better_string
innerhalb des enthaltenen Bereichs Änderungen vornehmen müssen, funktioniert diese Lösung nicht. Der Anwendungsfall für die Erfassung als const-ref ist, wenn die Variable im enthaltenen Bereich veränderbar sein muss, jedoch nicht im Lambda.const string &c_better_string = better_string;
und sie glücklich an das Lambda übergeben können:[&c_better_string]
Ich denke, wenn Sie die Variable nicht als Parameter des Funktors verwenden, sollten Sie die Zugriffsebene der aktuellen Funktion verwenden. Wenn Sie denken, Sie sollten nicht, dann trennen Sie Ihr Lambda von dieser Funktion, es ist nicht Teil davon.
Auf jeden Fall können Sie auf einfache Weise dasselbe erreichen, was Sie möchten, indem Sie stattdessen eine andere const-Referenz verwenden:
Dies entspricht jedoch der Annahme, dass Ihr Lambda von der aktuellen Funktion isoliert werden muss, sodass es kein Lambda ist.
quelle
best_string
nur. Abgesehen davon "lehnt" GCC 4.5 den Code wie beabsichtigt erfolgreich ab.Ich denke, Sie haben drei verschiedene Möglichkeiten:
mit einer Kopie
Das Interessante an Lambdas mit Copy Captures ist, dass diese tatsächlich schreibgeschützt sind und daher genau das tun, was Sie möchten.
mit std :: bind
std::bind
reduziert die Arität einer Funktion. Beachten Sie jedoch, dass dies über einen Funktionszeiger zu einem indirekten Funktionsaufruf führen kann / wird.quelle
Es gibt einen kürzeren Weg.
Beachten Sie, dass vor "best_string" kein kaufmännisches Und steht.
Es wird vom Typ "const std :: reference_wrapper << T >>" sein.
http://coliru.stacked-crooked.com/a/0e54d6f9441e6867
quelle
Verwenden Sie clang oder warten Sie, bis dieser gcc-Fehler behoben ist: Fehler 70385: Lambda-Erfassung durch Referenz der const-Referenz schlägt fehl [ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70385 ]
quelle
Wenn Sie eine Konstante verwenden, setzt der kaufmännische Und-Wert des Algorithmus die Zeichenfolge auf den ursprünglichen Wert. Mit anderen Worten, das Lambda definiert sich nicht wirklich als Parameter der Funktion, obwohl der umgebende Bereich eine zusätzliche Variable hat ... Ohne sie zu definieren Die Zeichenfolge wird jedoch nicht als typische [&, & best_string] (Zeichenfolgenkonstante) definiert. Daher ist es höchstwahrscheinlich besser, wenn wir sie einfach dabei belassen und versuchen, die Referenz zu erfassen.
quelle