Frage

Ist es möglich, Erfassung durch konstante Referenz in einem Lambda-Ausdruck?

Ich mag die Zuordnung unten markiert scheitern, 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, könnte es gut sein, sie zu aktualisieren, wenn es Einrichtungen in C ++ 14 Hilfe bei dieser. Ist die Erweiterungen in C ++ 14 ermöglicht es uns, ein nicht-konstantes Objekt durch konstante Referenz zu erfassen? ( August 2015 )

War es hilfreich?

Lösung

const ist in der Grammatik nicht für Aufnahmen ab n3092:

capture:
  identifier
  & identifier
  this

Der Text nur erwähnen Capture-by-Kopie und Capture-by-reference und erwähnt nicht, jede Art von const-ness.

Man fühlt sich wie ein Versehen zu mir, aber ich habe nicht den Standardisierungsprozess sehr genau verfolgt.

Andere Tipps

C ++ 14:

[&best_string = static_cast<const std::string&>(best_string)](const string& s)
{
    best_string = s; // fails
};

DEMO


C ++ 17:

[&best_string = std::as_const(best_string)](const string& s)
{
    best_string = s; // fails
};

DEMO 2

ich glaube, das Capture-Teil nicht const, da die Aufnahmemittel angeben sollte, es müssen nur einen Weg, um den Zugang der äußere Umfang variabel.

Der Bezeichner ist besser in dem äußeren Umfang angegeben.

const string better_string = "XXX";
[&better_string](string s) {
    better_string = s;    // error: read-only area.
}

Lambda-Funktion ist const (kann in ihrem Umfang nicht Wertänderung), so dass, wenn Sie Capture-Variable nach Wert, kann die Variable nicht geändert werden, aber die Referenz in dem Lambda-Bereich ist es nicht.

Ich denke, wenn Sie nicht die Variable als Parameter des Funktors verwenden, dann sollten Sie die Zugriffsebene der aktuellen Funktion. Wenn Sie denken, Sie sollen nicht, dann trennen Ihr Lambda von dieser Funktion, es ist nicht ein Teil davon.

Wie auch immer, können Sie leicht erreichen die gleiche Sache, dass Sie unter Verwendung eines anderen konstante Referenz wollen statt:

#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";
    const string& string_processed = best_string;

    for_each( &strings[0], &strings[num_strings], [&string_processed]  (const string& s)  -> void 
    {
        string_processed = s;    // this should fail
    }
    );
    return 0;
}

Aber das ist die gleiche wie unter der Annahme, dass Ihr Lambda hat von der aktuellen Funktion isoliert wird, ist es ein nicht-Lambda zu machen.

Ich glaube, Sie drei verschiedene Möglichkeiten:

  • nicht konstante Referenz verwenden, sondern eine Kopie Capture verwenden
  • ignorieren die Tatsache, dass es modifizierbar ist
  • Verwendung std :: bind zu binden ein Argument einer binären Funktion, die eine konstante Referenz hat.

mit einer Kopie

Der interessante Teil über lambdas mit Kopie erfaßt ist, dass die tatsächlich nur gelesen werden, und deshalb genau tun, was Sie wollen, dass sie.

int main() {
  int a = 5;
  [a](){ a = 7; }(); // Compiler error!
}

mit std :: bind

std::bind reduziert die arity einer Funktion. Beachten Sie jedoch, dass diese Macht / wird über einen Funktionszeiger auf einen indirekten Funktionsaufruf führen.

int main() {
  int a = 5;
  std::function<int ()> f2 = std::bind( [](const int &a){return a;}, a);
}

Es gibt einen kürzeren Weg.

Beachten Sie, dass es keinen Ampersand vor "best_string".

Es wird von einem "const std :: reference_wrapper << T >>" Typ sein.

[best_string = cref(best_string)](const string& s)
{
    best_string = s; // fails
};

http://coliru.stacked-crooked.com/a/0e54d6f9441e6867

Mit Klappern oder warten, bis dieser gcc Fehler ist behoben: Fehler 70385: Lambda-Capture durch Verweis von const-Referenz nicht [ https: // gcc. gnu.org/bugzilla/show_bug.cgi?id=70385 ]

ein const verwenden einfach den Algorithmus haben kaufmännisches Und die Zeichenfolge auf seinen ursprünglichen Wert ist, Mit anderen Worten wird das Lambda definiert nicht wirklich selbst als Parameter der Funktion, wenn der umgebende Rahmen wird eine zusätzliche Variable ... allerdings ohne ihn zu definieren, wäre es nicht die Zeichenfolge als die typischen definieren [&, & best_string] (string const s) Deshalb , sein höchstwahrscheinlich besser, wenn wir es nur dabei belassen, versuchen, die Referenz zu erfassen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top