I need to loop through a vector in 2 different member functions. One calls the object's void update(); function, and the other calls the void render(SDL_Renderer *rdr) const function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
SDL_Rect scope{camera.getX() / Tile::size,
camera.getY() / Tile::size,
(camera.getX() + game.getWindowWidth()) / Tile::size,
(camera.getY() + game.getWindowHeight()) / Tile::size};
if (scope.x < 0) scope.x = 0;
if (scope.w > width) scope.w = width;
if (scope.y < 0) scope.y = 0;
if (scope.h > height) scope.h = height;
for (int x = scope.x; x < scope.w; ++x)
{
for (int y = scope.y; y < scope.h; ++y)
{
//In update: tiles[x + y * width]->update(); in render: tiles[x + y * width]->render(rdr);
}
}
How should I do this without duplicating the code?
There are a number of options, but it depends on context.
One generalized approach is to consider std::bind, where you provide to this generic function a function object. Sometimes this may require to make this a template function accepting any time of function object.
Basically, you're calling update or render based on what function object is provided.
This can also be implemented without making a template function by using a virtual (possibly abstract) calls with a "do" function, where the parameter to this generic function is of the base type, but the virtual override in the derived class selects for update or render.
Some choose to do with with a simple integer, indicating an instruction, conditionally calling update or render.
If you research the std::sort algorithm, you'll notice the user supplies a function object to perform the comparison. The theory here is similar.
I thought that was generally considered bad design.
I wouldn't disagree, but it is also central to most message based implementations.
There's a ton of ancient C code that works by switch or "if/else" on an integer (instead of using pointers to functions).
Strangely, with careful testing it can be demonstrated that switch on integer can be faster than call by function pointer or function object.
The exception, in the case of function objects in C++, is where the function object performs the work itself and can be expanded inline.
It's also used in student code when calling a function by pointer, or using std::bind just isn't at the student's level, and virtual functions aren't even yet exposed.
Good point about message based imps (like the giant switches in window procedures). And a switch can yield very fast dispatch using a jump table, although it's not immediately obvious that it would be faster than an indirect function call.
Thanks for the help. A pointer-to-member-function (I used std::function<void(Tile &tile)> rather than C style function pointers) does exactly what I need.