Le code suivant se compile avec gcc 4.5.1 mais pas avec VS2010 SP1:
#include <iostream>
#include <vector>
#include <map>
#include <utility>
#include <set>
#include <algorithm>
using namespace std;
class puzzle
{
vector<vector<int>> grid;
map<int,set<int>> groups;
public:
int member_function();
};
int puzzle::member_function()
{
int i;
for_each(groups.cbegin(),groups.cend(),[grid,&i](pair<int,set<int>> group){
i++;
cout<<i<<endl;
});
}
int main()
{
return 0;
}
Voici l'erreur:
error C3480: 'puzzle::grid': a lambda capture variable must be from an enclosing function scope
warning C4573: the usage of 'puzzle::grid' requires the compiler to capture 'this' but the current default capture mode does not allow it
Alors,
1> quel compilateur a raison?
2> Comment puis-je utiliser des variables membres dans un lambda dans VS2010?
pair<const int, set<int> >
, c'est le type de paire réel d'une carte. Il devrait également s'agir d'une référence à const.Réponses:
Je pense que VS2010 a raison cette fois-ci, et je vérifierais si j'avais la norme à portée de main, mais actuellement je ne l'ai pas.
Maintenant, c'est exactement comme le message d'erreur dit: Vous ne pouvez pas capturer des éléments en dehors de la portée englobante du lambda. †
grid
n'est pas dans la portée englobante, maisthis
est (chaque accès àgrid
se produit en fait commethis->grid
dans les fonctions membres). Pour votre cas d'utilisation, la capturethis
fonctionne, car vous l'utiliserez tout de suite et vous ne voulez pas copier legrid
Si toutefois vous souhaitez stocker la grille et la copier pour un accès ultérieur, là où votre
puzzle
objet peut déjà être détruit, vous devrez faire une copie locale intermédiaire:† Je simplifie - Google pour "atteindre la portée" ou voir §5.1.2 pour tous les détails sanglants.
la source
tmp
êtreconst &
àgrid
de réduire la copie? Nous voulons toujours au moins une copie, la copie dans le lambda ([tmp]
), mais pas besoin d'une deuxième copie.grid
bien qu'elle soit probablement optimisée. Plus court et mieux c'est:auto& tmp = grid;
etc.[grid = grid](){ std::cout << grid[0][0] << "\n"; }
éviter la copie supplémentaireerror: capture of non-variable ‘puzzle::grid’
Résumé des alternatives:
capturer
this
:utiliser une référence locale au membre:
C ++ 14:
exemple: https://godbolt.org/g/dEKVGD
la source
[&grid]
ne fonctionne toujours pas). Très content de le savoir!Je crois que vous devez capturer
this
.la source
grid
directement. Le problème étant, que faire si vous souhaitez copier la grille? Cela ne vous permettra pas de faire cela.Une autre méthode qui limite la portée du lambda plutôt que de lui donner accès à l'ensemble
this
est de passer une référence locale à la variable membre, par exemplela source