- Remove From My Forums
-
Question
-
std::unique_lock<std::mutex> lk(mut); data_cond.wait(lk, []{return !data_queue.empty();});
error at
data_cond.wait(lk, []{return !data_queue.empty();});
‘this’ was not captured for this lambda function
where std::condition_variable data_cond; std::queue<T> data_queue;
Sigma : Every day has new and fresh idea and then search whether exists,
Answers
-
-
Marked as answer by
沈世鈞
Friday, November 4, 2011 8:57 AM
-
Marked as answer by
All replies
-
Seems pretty clear — data_queue is a member of a class/struct object. The lambda needs to know which object to operate on, however you didn’t tell it, and you didn’t allow it to capture the implicit this needed to access data_queue. You
can add a capture clause letting the compiler know you want to capture it though like// Disclaimer, I do Windows CE development, which doesn't // have Lambda support yet, so I am doing this from memory // I might have the syntax wrong data_cond.wait(lk, [this]{return !data_queue.empty();});
Of course, you need to make absolutely certain that your object will outlive the lambda in this case.
-
after tried, invalid type argument it’s my first time to see this kind of writing, [this]{} what does this mean?
Sigma : Every day has new and fresh idea and then search whether exists,
-
It means you want the lambda to capture the «this» pointer.
Here is an example that might help.If you are unfamiliar with the concept of the «this» pointer, it is a pointer to the object whose member function you are calling. For example,
class Foo { public: int x; void function() { x = 3; // these lines do the same thing this->x = 3; // } };
A «this» pointer is available to every member function. It is almost like it is an implicit first parameter passed to every member function.
Foo f;
f.function(); // how you normally call an object’s member function
In an alternate language that didn’t have implicit «this» pointers, you might instead define things like:
class Foo { public: int x; void function(Foo * const the_this_pointer) { the_this_pointer->x = 3; } };
And call them like this:
function(f);
-
why invalid argument , data_cond.wait(lk, [this]{return !data_queue.empty();});?
Sigma : Every day has new and fresh idea and then search whether exists,
-
-
Marked as answer by
沈世鈞
Friday, November 4, 2011 8:57 AM
-
Marked as answer by
|
|
|
‘this’ was not captured for this lambda function
- Подписаться на тему
- Сообщить другу
- Скачать/распечатать тему
|
|
Код такой: void BitOStream::WriteString(std::string str) { for_each(str.begin(), str.end(), [](char c) { WriteByte(c); } ); } Компилятор(g++ 4.5) выдает: BitOStream.cpp: In lambda function: BitOStream.cpp:45:3: ошибка: ‘this’ was not captured for this lambda function make: *** [flactrim] Ошибка 1 WriteByte это приватный метод того же класса: void WriteByte(uint8_t byte, unsigned short bitCount = BITSINBYTE); Как исправить ошибку? |
Flex Ferrum |
|
Цитата miksayer @ 04.06.10, 12:59 void BitOStream::WriteString(std::string str) { for_each(str.begin(), str.end(), [this](char c) { WriteByte©; } ); } и твой код будет мягким и шелковистым. |
miksayer |
|
Цитата Flex Ferrum @ 04.06.10, 13:01 и твой код будет мягким и шелковистым.
спасибо Добавлено 04.06.10, 13:05 |
Flex Ferrum |
|
Цитата miksayer @ 04.06.10, 13:04 и, кстати, зачем здесь указывать this в квадратных скобках? т.е. мы говорим компилятору, что мы планируем работать с this в самом выражении?
В квадратных скобках указывается т. н. «capture-list» — перечень переменных, видимых в контексте определения лямбда-функции, который должен быть доступен в её теле. Ты перечисляешь либо конкретные переменные, либо используешь специальные формы: |
miksayer |
|
спасибо |
0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
0 пользователей:
- Предыдущая тема
- C/C++: Общие вопросы
- Следующая тема
[ Script execution time: 0,0336 ] [ 16 queries used ] [ Generated: 9.02.23, 15:29 GMT ]
Hi,
and first, thanks a lot for this amazing piece of code
When I try to build my app including the v8pp ‘class’ headers, I get the following error.
Would you have any idea about what’s happening ?
Thanks in advance.
compile output:
g++ -c -m64 -pipe -g -w -std=c++11 -I../../3rdparty/desktop/include/v8 -Isrc -o build/desktop/obj/javascriptTest.o src/javascriptTest.cpp
In file included from src/javascriptTest.cpp:21:0:
../../main/src/javascript/v8pp/class.hpp: In instantiation of ‘v8pp::detail::class_singleton<T>::class_singleton(v8::Isolate*, v8pp::detail::class_info::type_index) [with T = Point; v8pp::detail::class_info::type_index = unsigned int]::<lambda(const v8::FunctionCallbackInfo<v8::Value>&)>’:
../../main/src/javascript/v8pp/class.hpp:178:5: required from ‘struct v8pp::detail::class_singleton<T>::class_singleton(v8::Isolate*, v8pp::detail::class_info::type_index) [with T = Point; v8pp::detail::class_info::type_index = unsigned int]::<lambda(const class v8::FunctionCallbackInfo<v8::Value>&)>’
../../main/src/javascript/v8pp/class.hpp:189:5: required from ‘v8pp::detail::class_singleton<T>::class_singleton(v8::Isolate*, v8pp::detail::class_info::type_index) [with T = Point; v8pp::detail::class_info::type_index = unsigned int]’
../../main/src/javascript/v8pp/class.hpp:261:4: required from ‘static v8pp::detail::class_singleton<T>& v8pp::detail::class_singleton<T>::instance(v8::Isolate*) [with T = Point; v8pp::detail::class_singleton<T> = v8pp::detail::class_singleton<Point>]’
../../main/src/javascript/v8pp/class.hpp:369:56: required from ‘v8pp::class_<T>::class_(v8::Isolate*) [with T = Point]’
src/javascriptTest.cpp:71:42: required from here
../../main/src/javascript/v8pp/class.hpp:183:74: error: ‘this’ was not captured for this lambda function
../../main/src/javascript/v8pp/class.hpp:183:74: error: return-statement with a value, in function returning 'void' [-fpermissive]
make: *** [build/desktop/obj/javascriptTest.o] Error 1
details:
file included from src/javascriptTest.cpp:21:0
being:v8pp/class.hpp
src/javascriptTest.cpp:71:42: required from here
being
v8pp::class_<Point> point_class(isolate);
(with Point being a basic int 2d-coord(x,y) class, no template or anything else)
my environment:
g++ (Debian 4.7.2-5) 4.7.2
#define V8_MAJOR_VERSION 4
#define V8_MINOR_VERSION 5
#define V8_BUILD_NUMBER 103
#define V8_PATCH_LEVEL 30
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 |
#include <iostream> #include <ctime> #include <vector> #include <windows.h> #include <sstream> #include <iomanip> #include <cmath> #include <algorithm> #include <string> #include <list> #include <cctype> using namespace std; void ClearScreen(); class Game; class Item; class Character { public: double accuraty; double agility; double endurance; int hitpoints; int experience; int level; int freeskills; int money; double speed; double strength; int distance; vector <Item> inventory; string object; Character (string o) : object(o) { cout << "Создался объект " << object << endl; } ~Character() { cout << "Разрушился объект " << object << " с хр " << hitpoints << endl; } int checklevel(); void inventoryShow(Game &); void useItem(Character &, int, Game &); void useChoiseItem(Game &, Character &); void generatecharacter(); void freeskillsassign(); }; class Battle; class Game { public: friend class Item; void showgamelogs(); void cleargamelogs(); void clearmainlogfromtemp(); string gamelogs; string tempgamelogs; string gamelogstats; vector <string> mainlog; vector <string> templog; void play(Game &); void roadjourney(Battle &, Character &, Character &, Item &, Game &); void healing(Character &, double); void bardisplay(Character &, Character &, Game &); void bardisplay(Character &, Game &); void osstostring( std::ostream& s ); void osstostringtemp( std::ostream& s ); void osstostring2( std::ostream& s ); }; void Game::osstostring( std::ostream& s ) { gamelogs = dynamic_cast<std::ostringstream&>(s).str(); mainlog.push_back(gamelogs); } void Game::osstostringtemp( std::ostream& s ) { tempgamelogs = dynamic_cast<std::ostringstream&>(s).str(); templog.push_back(tempgamelogs); } void Game::osstostring2( std::ostream& s ) { gamelogstats += dynamic_cast<std::ostringstream&>(s).str(); } // int CounterClear = 0; // int BarCounter = 0; void Game::showgamelogs() { // ++CounterClear; // cout << "Число логов: " << CounterClear << "nЧисло баров: " << BarCounter << endl; ClearScreen(); if (templog.size() > 0) { for (auto vectorit = mainlog.begin(); vectorit != mainlog.end(); ++vectorit) gamelogs += *vectorit; for (auto vectorit = templog.begin(); vectorit != templog.end(); ++vectorit) tempgamelogs += *vectorit; cout << gamelogstats << gamelogs << tempgamelogs; } else { for (auto vectorit = mainlog.begin(); vectorit != mainlog.end(); ++vectorit) gamelogs += *vectorit; cout << gamelogstats << gamelogs; } tempgamelogs = ""; gamelogs = ""; gamelogstats = ""; } void Game::cleargamelogs() { mainlog.clear(); templog.clear(); } void Game::clearmainlogfromtemp() { auto pred = [&templog](const std::string& key) ->bool { return std::find(templog.begin(), templog.end(), key) != templog.end(); }; mainlog.erase(std::remove_if(mainlog.begin(), mainlog.end(), pred), mainlog.end()); } void Game::healing(Character &p, double h) { p.hitpoints += h; if (p.hitpoints > 100) p.hitpoints = 100; } int Character::checklevel() { if (experience >= (250 * (pow(level,(5-1))))) { level += 1; freeskills +=3; return 1; } else return 0; } class Battle : public Game { private: public: string object; Battle (string o) : object(o) { cout << "Создался объект " << object << endl; } ~Battle() { cout << "Разрушился объект " << object << endl; } void callopponent(Character &, Character &, Item &, Game &); void battlelogic(Character &, Character &, Item &, Game &); void battledistance(Character &, Character &, Game &); void battlehit(Character &, Character &, Game &); void battledamage(Character &, Character &, Game &); void surrendlogic(Character &, Character &, Game &); void opponentTurn(Character &, Character &, Item &, Game &); }; class Item { public: string name; string type; double weight; double damage; double healing; friend bool operator==(const Item& lhs, const Item& rhs) { return lhs.name == rhs.name && lhs.type == rhs.type; } void itemDrop(Character &p, Game &game); void itemToThrow(Character &p); }; void Item::itemDrop(Character & p, Game & game) { vector<Item> randomitems = {{"Молот","Оружие",10,20,0},{"Топор","Оружие",20,10,0},{"Меч","Оружие",10,30,0} ,{"Маленькое зелье","Зелье",1,0,10},{"Среднее зелье","Зелье",3,0,25},{"Большое зелье","Зелье",5,0,50}}; int itemcount = 0; int chance = 0; for (int i = 0; i != 1; ++i) { itemcount = (rand() % 4) + 0; switch (itemcount) { case 0: chance = 50; if((rand() % 100) + 1 > chance) --i; break; case 1: chance = 40; if((rand() % 100) + 1 > chance) --i; break; case 2: chance = 30; if((rand() % 100) + 1 > chance) --i; break; case 3: chance = 20; if((rand() % 100) + 1 > chance) --i; break; } } if (itemcount > 1) { vector <Item> dropoutput; for (int i = 0; i != itemcount; ++i) { int randomIndex = rand() % randomitems.size(); if (randomitems[randomIndex].name == "Большое зелье") { chance = 5; if((rand() % 100) + 1 < chance) dropoutput.push_back(randomitems[randomIndex]); else --i; continue; } else if (randomitems[randomIndex].name == "Маленькое зелье") { chance = 25; if((rand() % 100) + 1 < chance) dropoutput.push_back(randomitems[randomIndex]); else --i; continue; } else if (randomitems[randomIndex].name == "Топор") { chance = 5; if((rand() % 100) + 1 < chance) dropoutput.push_back(randomitems[randomIndex]); else --i; continue; } else if (randomitems[randomIndex].name == "Меч") { chance = 5; if((rand() % 100) + 1 < chance) dropoutput.push_back(randomitems[randomIndex]); else --i; continue; } else if (randomitems[randomIndex].name == "Молот") { chance = 5; if((rand() % 100) + 1 < chance) dropoutput.push_back(randomitems[randomIndex]); else --i; continue; } else if (randomitems[randomIndex].name == "Среднее зелье") { chance = 15; if((rand() % 100) + 1 < chance) dropoutput.push_back(randomitems[randomIndex]); else --i; continue; } } game.osstostring(ostringstream().flush() << "После боя вы находите трофеи: " << endl); int ch = 0; do { game.osstostringtemp(ostringstream().flush() << "Выберите вещи по номерами позиций или A, если хотите забрать их" << " или n, чтобы выйти из боя. " << endl); int c = 1; for (auto vectorit = dropoutput.begin(); vectorit != dropoutput.end(); ++vectorit,++c) { game.osstostringtemp(ostringstream().flush() << c << ". " << (*vectorit).name << endl); } game.showgamelogs(); cin >> ch; p.inventory.push_back(dropoutput[(ch - 1)]); dropoutput.erase(dropoutput.begin() + (ch - 1)); game.osstostring(ostringstream().flush() << "Вы выбрали " << dropoutput[(ch - 1)].name << endl); } while (ch != 0 && dropoutput.size() > 0); } game.clearmainlogfromtemp(); } void Item::itemToThrow(Character &p) { string itemtodrop; cout << "Которую вещь вы хотите бросить?" << endl; getline(cin, itemtodrop); Item temp; for (auto vectorit = p.inventory.begin(); vectorit != p.inventory.end(); ++vectorit) { if ((*vectorit).name == itemtodrop) { temp = {(*vectorit)}; break; } } auto it = find(p.inventory.begin(),p.inventory.end(), temp); if(it != p.inventory.end()) p.inventory.erase(it); } void Character::inventoryShow(Game &game) { int c = 1; for (auto vectorit = inventory.begin(); vectorit != inventory.end(); ++vectorit, ++c) { if ((*vectorit).type == "Оружие") { cout << c << ". " << "Оружие: " << (*vectorit).name; cout << " - Урон: " << (*vectorit).damage << endl; } else if ((*vectorit).type == "Зелье") { cout << c << ". " << "Зелье: " << (*vectorit).name; cout << " - Лечельный эффект: " << (*vectorit).healing << endl; } } } void Character::useItem(Character &p, int ich, Game &game) { if(inventory[ich].type == "Зелье") { game.healing(p, inventory[ich].healing); p.inventory.erase(inventory.begin() + ich); } else cout << "Test" << endl; } void Character::useChoiseItem(Game &game, Character &p) { int ich; cout << "Будете что-то использовать/поменять или выйдете? Выберите номер позиции для применения или n для выхода." << endl; cin >> ich; if (ich > 0) { useItem(p,(ich - 1), game); if (inventory[ich - 1].type == "Зелье") game.osstostring(ostringstream().flush() << "Вы вылечились на " << inventory[ich - 1].healing << endl); } else if (ich == 0) { game.osstostringtemp(ostringstream().flush() << "Вы вышли из инвентаря" << endl); } else game.osstostringtemp(ostringstream().flush() << "У вас пустой инвентарь!" << endl); } void Game::play(Game &game) { Character p("Vova"); p.inventory.push_back({"Маленькое зелье","Зелье",1,0,10}); p.inventory.push_back({"Среднее зелье","Зелье",1,0,25}); p.inventory.push_back({"Большое зелье","Зелье",1,0,50}); Item i; p.generatecharacter(); Battle b("Battle"); Character o("Oppo"); int ch = 0; while (p.hitpoints > 0) { if (p.freeskills == 0) { cout << "Вы на пути. Что будете делать?n1) Идти дальше.n2) Посмотреть инвентарь.n"; cin >> ch; switch (ch) { case 1: roadjourney(b, p, o, i, game); break; case 2: p.inventoryShow(game); p.useChoiseItem(game,p); break; } } else { cout << "Вы на пути. Что будете делать?n1) Идти дальше.n2) Посмотреть инвентарь.n" << "3) Назначить свободное количество очок(" << p.freeskills << ")" << endl; cin >> ch; switch (ch) { case 1: roadjourney(b, p, o, i, game); break; case 2: p.inventoryShow(game); p.useChoiseItem(game,p); break; case 3: p.freeskillsassign(); break; } } } } void Game::roadjourney(Battle &b, Character &p, Character &o, Item &i, Game &game) { int fate = (rand() % 3) + 1; switch (fate) { case 1: b.callopponent(p, o, i, game); break; case 2: cout << "Вы ходите дальше" << endl; break; case 3: cout << "Вы находите сокровище" << endl; break; } } void Game::bardisplay(Character &p, Character &o, Game &game) { vector <string> pskillnames = {"Сила","Ловкость","Точность","Выносливость","Скорость", "Здоровье"}; vector <double> pskillstats = {p.strength,p.agility,p.accuraty,p.endurance,p.speed, p.hitpoints}; vector <string> oskillnames = {"Сила","Ловкость","Точность","Выносливость","Скорость", "Здоровье"}; vector <double> oskillstats = {o.strength,o.agility,o.accuraty,o.endurance,o.speed, o.hitpoints}; if (p.object == "Vova") { game.osstostring2(ostringstream().flush() << "Ваши характеристики: Характеристики противника: " << endl); for (int n = 0, s = 0, i = 6;s < i;n++, s++) if (pskillstats[n] == 10 && n != 0) { game.osstostring2(ostringstream().flush() << pskillnames[n] << ":t" << pskillstats[n] << setw(51) << oskillnames[n] << ":t" << oskillstats[n] << endl); continue; } else if (pskillstats[n] == p.hitpoints) { game.osstostring2(ostringstream().flush() << pskillnames[n] << ":t" << pskillstats[n] << setw(50) << oskillnames[n] << ":t" << oskillstats[n] << endl); continue; } else if (pskillstats[n] == 10 && n == 0) { game.osstostring2(ostringstream().flush() << pskillnames[n] << ":tt" << pskillstats[n] << setw(51) << oskillnames[n] << ":t" << oskillstats[n] << endl); continue; } else if (pskillnames[n].size() < 6) { game.osstostring2(ostringstream().flush() << pskillnames[n] << ":tt" << pskillstats[s] << setw(52) << oskillnames[n] << ":t" << oskillstats[s] << endl); continue; } else { game.osstostring2(ostringstream().flush() << pskillnames[n] << ":t" << pskillstats[s] << setw(52) << oskillnames[n] << ":t" << oskillstats[s] << endl); continue; } } else { game.osstostring2(ostringstream().flush() << "Ваши характеристики: Характеристики противника: " << endl); for (int n = 0, s = 0, i = 6;s < i;n++, s++) { if (oskillstats[n] == 10 && n != 0) { game.osstostring2(ostringstream().flush() << oskillnames[n] << ":t" << oskillstats[n] << setw(51) << pskillnames[n] << ":t" << pskillstats[n] << endl); continue; } else if (oskillstats[n] == o.hitpoints) { game.osstostring2(ostringstream().flush() << oskillnames[n] << ":t" << oskillstats[n] << setw(50) << pskillnames[n] << ":t" << pskillstats[n] << endl); continue; } else if (oskillstats[n] == 10 && n == 0) { game.osstostring2(ostringstream().flush() << oskillnames[n] << ":tt" << oskillstats[n] << setw(51) << pskillnames[n] << ":t" << pskillstats[n] << endl); continue; } else if (oskillnames[n].size() < 6) { game.osstostring2(ostringstream().flush() << oskillnames[n] << ":tt" << oskillstats[s] << setw(52) << pskillnames[n] << ":t" << pskillstats[s] << endl); continue; } else { game.osstostring2(ostringstream().flush() << oskillnames[n] << ":t" << oskillstats[s] << setw(52) << pskillnames[n] << ":t" << pskillstats[s] << endl); continue; } } } } void Game::bardisplay(Character &p, Game &game) { vector <string> pskillnames = {"Сила","Ловкость","Точность","Выносливость","Скорость","Здоровье","Уровень","Опыт"}; vector <double> pskillstats = {p.strength,p.agility,p.accuraty,p.endurance,p.speed,p.hitpoints,p.level,p.experience}; game.osstostring2(ostringstream().flush() << "Ваши характеристики:" << endl); for (int n = 0, s = 0, i = 8;s < i;n++, s++) { if (pskillstats[n] == 10 && n != 0) { game.osstostring2(ostringstream().flush() << pskillnames[n] << ":t" << pskillstats[n] << endl); continue; } else if (pskillstats[n] == 10 && n == 0) { game.osstostring2(ostringstream().flush() << pskillnames[n] << ":tt" << pskillstats[n] << endl); continue; } else if (pskillnames[n].size() < 6) { game.osstostring2(ostringstream().flush() << pskillnames[n] << ":tt" << pskillstats[s] << endl); continue; } else { game.osstostring2(ostringstream().flush() << pskillnames[n] << ":t"<< pskillstats[s] << endl); continue; } } } int main() { setlocale(LC_ALL,"Rus"); srand(time(0)); Game game; game.play(game); } |
Description
Maxim Ivanov
2011-12-10 05:51:57 UTC
Consider the following source code: struct A { static void f() {} void foo() { [] () { f(); }; } }; GCC 4.6.1 produces the following error message when compiling it: test.cpp: In lambda function: test.cpp:7:27: error: ‘this’ was not captured for this lambda function However, the member function f is static and it's call doesn't use 'this'; therefore the lambda need not to capture 'this'. The code shall compile.
Comment 1
Paolo Carlini
2011-12-22 01:38:46 UTC
On it.
Comment 2
Andy Lutomirski
2012-05-03 21:53:18 UTC
This seems to have gotten worse in gcc 4.7. This code is now rejected as well: This code: struct A { static void func1() {} }; template<typename T> struct B : public A { void func2() const { func3([&]{ func1(); }); } template<typename Func> void func3(Func f) const { } }; template class B<int>; The error is: template_bug.cc: In instantiation of ‘B<T>::func2() const [with T = int]::<lambda()>’: template_bug.cc:11:22: required from ‘struct B<T>::func2() const [with T = int]::<lambda()>’ template_bug.cc:11:5: required from ‘void B<T>::func2() const [with T = int]’ template_bug.cc:20:16: required from here template_bug.cc:11:16: error: redeclaration of ‘const B<int>* const B<T>::func2() const [with T = int]::<lambda()>::__this’ template_bug.cc:11:22: note: previous declaration ‘const B<int>* const B<T>::func2() const [with T = int]::<lambda()>::__this’ template_bug.cc:11:16: error: redeclaration of ‘const B<int>* const this’ template_bug.cc:11:22: error: ‘const B<int>* const this’ previously declared here template_bug.cc:15:8: error: ‘void B<T>::func3(Func) const [with Func = B<T>::func2() const [with T = int]::<lambda()>; T = int]’, declared using local type ‘B<T>::func2() const [with T = int]::<lambda()>’, is used but never defined [-fpermissive] Your patch fixes this test case, too.
Comment 4
gcc-bugx
2012-06-04 08:21:54 UTC
Probably related error: this capture ignored on explicit instantiation. --------------------8<--------------- struct A { static void f() {} template <typename T> void foo() { [this] () { f(); }; } }; template void A::foo<int>(); -------------------->8--------------- Compiler version & output: $ g++ -std=c++11 -c -v y.cc Using built-in specs. COLLECT_GCC=g++ Target: x86_64-unknown-linux-gnu Configured with: ./configure --enable-languages=c,c++ --prefix=/home/x Thread model: posix gcc version 4.7.0 (GCC) COLLECT_GCC_OPTIONS='-std=c++11' '-c' '-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64' /home/x/libexec/gcc/x86_64-unknown-linux-gnu/4.7.0/cc1plus -quiet -v -D_GNU_SOURCE y.cc -quiet -dumpbase y.cc -mtune=generic -march=x86-64 -auxbase y -std=c++11 -version -o /tmp/ccdFvfri.s GNU C++ (GCC) version 4.7.0 (x86_64-unknown-linux-gnu) compiled by GNU C version 4.7.0, GMP version 4.3.2, MPFR version 3.0.0-p8, MPC version 0.9 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 ignoring nonexistent directory "/home/x/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../x86_64-unknown-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /home/x/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0 /home/x/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/x86_64-unknown-linux-gnu /home/x/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/backward /home/x/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/include /usr/local/include /home/x/include /home/x/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/include-fixed /usr/include End of search list. GNU C++ (GCC) version 4.7.0 (x86_64-unknown-linux-gnu) compiled by GNU C version 4.7.0, GMP version 4.3.2, MPFR version 3.0.0-p8, MPC version 0.9 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: ... y.cc: In instantiation of ‘A::foo() [with T = int]::<lambda()>’: y.cc:8:4: required from ‘struct A::foo() [with T = int]::<lambda()>’ y.cc:8:3: required from ‘void A::foo() [with T = int]’ y.cc:11:27: required from here y.cc:8:17: error: ‘this’ was not captured for this lambda function
Comment 5
Jason Merrill
2012-06-04 19:35:40 UTC
The testcases in comments 2 and 4 are PR 53137, which is fixed for 4.7.1.
Comment 6
Paolo Carlini
2012-08-16 09:53:36 UTC
Not actively working on this.
Comment 7
kpx1894
2012-12-07 15:18:03 UTC
This bug is still present in GCC 4.7.2. There are cases where capturing "this" (as a workaround) is not possible: ---------- #include <iostream> struct Test { void (*get())() { return [](){ Test::sf(); }; } static void sf() { std::cout << "Test::sf" << std::endl; } }; int main() { Test test; auto f = test.get(); (*f)(); } ----------
Comment 8
Jason Merrill
2013-03-04 18:15:08 UTC
*** Bug 55828 has been marked as a duplicate of this bug. ***
Comment 9
Jason Merrill
2013-03-08 16:03:57 UTC
Author: jason Date: Fri Mar 8 16:03:48 2013 New Revision: 196549 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=196549 Log: PR c++/51494 PR c++/51884 PR c++/56222 * tree.c (maybe_dummy_object): Don't capture 'this'. * semantics.c (maybe_resolve_dummy): New. (finish_non_static_data_member): Use it. (finish_qualified_id_expr): Don't test is_dummy_object. * cp-tree.h: Declare maybe_resolve_dummy. * call.c (build_new_method_call_1): Use it. Added: trunk/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this11.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/call.c trunk/gcc/cp/cp-tree.h trunk/gcc/cp/semantics.c trunk/gcc/cp/tree.c
Comment 10
Jason Merrill
2013-03-08 16:10:48 UTC
Fixed for 4.8.
Comment 11
Arthur O’Dwyer
2015-11-24 01:18:22 UTC
Is there a workaround available for GCC 4.6.3? That is, I have some code that looks like class A { static A *unwrap(void *p); static void api_helper(void *p) { A *a = unwrap(p); ... } void init() { register_with_api(&api_helper); } }; where "api_helper" exists only to conform to the requirements of the external API. To reduce the surface area of the class, I'd like to refactor this into something like class A { static A *unwrap(void *p); void init() { auto api_helper = [](void *a) { A *a = unwrap(p); ... }; register_with_api(api_helper); } }; but at the moment I'm hitting this bug in gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 because "api_helper" happens to also want to use some static members of A. I understand if there's no workaround (beyond "upgrade to gcc 4.8"), but if there IS one, I'd like to know it!
У меня есть небольшая проблема, и я не могу понять, почему этот код не работает:
std::for_each(users.begin(), users.end(), [](Wt::WString u)
{
std::cout << "ilosc: " << users.size() << std::endl;
userBox_->addItem(u);
});
Ошибки, которые я получаю при компиляции:
GameWidget.cpp: In lambda function:
GameWidget.cpp:352:30: error: 'users' is not captured
GameWidget.cpp:353:4: error: 'this' was not captured for this lambda function
GameWidget.cpp: In member function 'virtual void GameWidget::updateUsers()':
GameWidget.cpp:354:3: warning: lambda expressions only available with -std=c++11 or -std=gnu++11 [enabled by default]
GameWidget.cpp:354:4: error: no matching function for call to 'for_each(std::set<Wt::WString>::iterator, std::set<Wt::WString>::iterator, GameWidget::updateUsers()::<lambda(Wt::WString)>)'
GameWidget.cpp:354:4: note: candidate is:
In file included from /usr/include/c++/4.7/algorithm:63:0,
from GameWidget.h:11,
from GameWidget.cpp:9:
/usr/include/c++/4.7/bits/stl_algo.h:4436:5: note: template<class _IIter, class _Funct> _Funct std::for_each(_IIter, _IIter, _Funct)
GameWidget.cpp:354:4: error: template argument for 'template<class _IIter, class _Funct> _Funct std::for_each(_IIter, _IIter, _Funct)' uses local type 'GameWidget::updateUsers()::<lambda(Wt::WString)>'
GameWidget.cpp:354:4: error: trying to instantiate 'template<class _IIter, class _Funct> _Funct std::for_each(_IIter, _IIter, _Funct)'
я использую gcc 4.7.3
так что, вероятно, поддержка C ++ 11 доступна для моего компилятора.
userBox_
это коллекция и BOOST_FOREACH
правильно работает для этого кода:
BOOST_FOREACH(Wt::WString i, users)
{
std::cout << "ilosc: " << users.size() << std::endl;
userBox_->addItem(i);
}
Спасибо за любой ответ, мне так любопытно, почему это так.
4
Решение
Лямбда, которую вы написали, не фиксирует никаких переменных контекста. Для этого проще всего добавить &
в список захвата лямбды. Это захватит все переменные контекста по ссылке, и вы сможете получить к ним доступ в лямбда-выражении.
std::for_each(users.begin(), users.end(), [&](Wt::WString u)
{
std::cout << "ilosc: " << users.size() << std::endl;
userBox_->addItem(u);
});
Я не понимаю, почему ты печатаешь users.size()
внутри цикла, потому что похоже, что результат будет одинаковым на каждой итерации. Если вы переместите это за пределы цикла и хотите получить более точный контроль над тем, что захватывает лямбда, вы можете изменить список захвата, чтобы захватывать только this
указатель. Это позволит вам получить доступ к переменной-члену userBox_
,
std::cout << "ilosc: " << users.size() << std::endl;
std::for_each(users.begin(), users.end(), [this](Wt::WString u)
{
userBox_->addItem(u);
});
MSDN имеет отличную статью, объясняющую Синтаксис лямбда-выражения в мельчайших подробностях.
Наконец, в вашем случае нет необходимости std::for_each
и лямбда. Было бы гораздо лаконичнее использовать диапазон на основе for
цикл для добавления элементов в коллекцию.
for( auto const& u: users ) {
userBox_->addItem(u);
}
8
Другие решения
Все, что вам нужно было знать, — это ошибки, которые вы получили.
Вы явно указали лямбда-выражению не перехватывать что-либо, используя «[]», что означает, что единственными переменными, к которым у него есть доступ внутри тела функции, являются параметры и глобальные переменные.
Неважно, какой тип userBox_, это переменная-член, поэтому лямбда должна захватывать «this».
Наконец, вы передаете по значению, что означает, что вы собираетесь дублировать каждый Wt :: WString. Вы можете вместо этого использовать
std::for_each(users.begin(), users.end(), [&](const Wt::WString& u) {
...
});
«&»захватывает по ссылке и захватит» это «для вас.
http://en.cppreference.com/w/cpp/language/lambda
1
Захват переменных пользователей означает объявление вашей лямбды как:
[users](Wt::WString u){...}
который пройдет users
как переменная только для чтения.
Чтобы быть в состоянии изменить users
, вам нужно объявить вашу лямбду как:
[&users](Wt::WString u){...}
0