I have an application that is creating maps for civilization V. As an interesting design choice I decided to create a couple of functions that would do the looping through the map for me. This way I could pass a function pointer or a lambda function to that function that goes through the whole map doing something to each tile. Reasoning behind this was if I or someone else would change the way the map is stored (from 2D array to a 2D vector or whatever) one would only need to change one function instead of the whole codebase.
Now the problem, here is some code first.
Error code.
case ALL_SNOW:
m.loop_through_limit([] (Tile* t) {
t = new Snow(t->get_x(), t->get_y());
return t;
}, x, y, width, height);
break;
case PTN_ONE:
m.loop_through_limit([&] (Tile* t) {
int cur_x = t->get_x();
int cur_y = t->get_y();
t = new Plains(cur_x, cur_y);
// if (y <= height/4 || y >= (height*3)/4) {
// Top quarter rows and bottom quarter rows
// t = new Ocean(cur_x, cur_y);
// } else if (cur_x <= width/4) {
// Leftmost columns
// t = new Ocean(cur_x, cur_y);
// } else if (cur_x >= (width*3)/4) {
// Rightmost columns
// t = new Desert(cur_x, cur_y);
// }
return t;
}, x, y, width, height);
break;
Definitions from header file.
void loop_through(void (*)(Tile* t));
void loop_through_limit(Tile* (*)(Tile* t), int start_x, int start_y, int width, int height);
Now the difference in each case isn’t much apart from the commented out code. This works fine. When I comment out that if statement block, then this is my output.
c++ -c -g -O3 -ffast-math -Wall -Weffc++ -std=c++0x -o tile_block.o tile_block.cpp
tile_block.cpp: In static member function ‘static void TileBlock::write(Map&, TileBlock::Patterns, int, int, int, int)’:
tile_block.cpp:82:35: error: no matching function for call to ‘Map::loop_through_limit(TileBlock::write(Map&, TileBlock::Patterns, int, int, int, int)::<lambda(Tile*)>, int&, int&, int&, int&)’
tile_block.cpp:82:35: note: candidate is:
map.h:26:10: note: void Map::loop_through_limit(Tile* (*)(Tile*), int, int, int, int)
map.h:26:10: note: no known conversion for argument 1 from ‘TileBlock::write(Map&, TileBlock::Patterns, int, int, int, int)::<lambda(Tile*)>’ to ‘Tile* (*)(Tile*)’
And I believe the problem comes when I start using the parameters I’m trying to capture by reference. Then it starts to turn into a “lambda” function instead of just a “function pointer”, maybe I’m just not getting it.
Any suggestions?
C++11 lambda are not function pointers if they capture variables. What you need is called
std::function, especially for the second function, because the lambda for that capture variables.So change these:
to these:
Now you can pass lambda to the above functions.