Domanda

E 'possibile la cattura mediante riferimento const in un'espressione lambda?

Voglio l'assegnazione segnato seguito a fallire, ad esempio:

#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;
}

Aggiornamento: Poiché si tratta di una vecchia questione, potrebbe essere buono per aggiornare, se ci sono strutture in C ++ 14 per aiutare con questo. Fare le estensioni in C ++ 14 ci permettono di catturare un oggetto non const per riferimento const? ( agosto 2015 )

È stato utile?

Soluzione

const non è nella grammatica per la cattura come di n3092:

capture:
  identifier
  & identifier
  this

Il testo menziona solo la cattura-by-copy e la cattura per riferimento e non menziona alcun tipo di const-ness.

Percepita una svista per me, ma non ho seguito il processo di standardizzazione molto da vicino.

Altri suggerimenti

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

Penso che la parte di acquisizione non dovrebbe specificare const, come i mezzi di cattura, solo bisogno di un modo per accedere alla variabile ambito esterno.

L'identificatore viene meglio specificato nel perimetro esterno.

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

funzione lambda è const (non può cambiare il valore nel suo ambito di applicazione), in modo che quando si cattura variabile in base al valore, la variabile non può essere cambiato, ma il riferimento non è nella portata lambda.

credo che se non si sta usando la variabile come un parametro del funtore, quindi si dovrebbe utilizzare il livello di accesso della funzione corrente. Se si pensa che non si dovrebbe, quindi separare il lambda da questa funzione, non è parte di essa.

In ogni caso, si può facilmente ottenere la stessa cosa che si desidera utilizzando un altro riferimento const invece:

#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;
}

Ma questo è lo stesso come se la tua lambda devono essere isolati dalla funzione corrente, che lo rende un non-lambda.

Penso che tu abbia tre diverse opzioni:

  • non utilizzare riferimento const, ma utilizzare una cattura copia
  • ignorare il fatto che è modificabile
  • uso std :: bind per collegare un argomento di una funzione binario che ha un riferimento const.

utilizzando una copia

La parte interessante di lambda con catture copia è che questi sono in realtà di sola lettura e quindi fare esattamente quello che loro vogliono.

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

using std :: bind

std::bind riduce l'arietà di una funzione. Nota tuttavia che questo potrebbe / porterà ad una chiamata di funzione indiretta tramite un puntatore a funzione.

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

C'è un modo più breve.

Si noti che non v'è alcuna commerciale prima di "best_string".

Sarà di un "const std :: reference_wrapper << >> T" tipo.

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

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

Usa clang o attendere fino a quando questo gcc bug è stato risolto: bug 70385: Lambda cattura da parte di riferimento di riferimento const non riesce [ https: // gcc. gnu.org/bugzilla/show_bug.cgi?id=70385 ]

Utilizzo di un const dovrà semplicemente l'algoritmo commerciale impostare la stringa al suo valore originale, In altre parole, il Lambda non sarà davvero definirsi come parametro della funzione, anche se il campo che circonda avrà una variabile in più ... Senza definirlo però, non sarebbe definire la stringa come tipico   [&, e best_string] (const string s) Quindi , il suo più probabile meglio se lasciamo le cose come stanno, cercando di catturare il riferimento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top