Best way to avoid code duplication?

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?
Last edited on
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.


Last edited on
You can factor out the scope calculation into its own function and call it in the functions that call update and render.

 
SDL_Rect scope = getScope(camera);

you could use a pointer-to-member-function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

class Tile {
public:
    void update() { std::cout << "update\n"; }
    void render() { std::cout << "render\n"; }
};

void invoke(Tile* tile, void(Tile::*f)()) {
    // ...
    (tile->*f)();
}

int main() {
    Tile tile;
    invoke(&tile, &Tile::update);
    invoke(&tile, &Tile::render);
}


Some choose to do with with a simple integer, indicating an instruction, conditionally calling update or render.

I thought that was generally considered bad design.
Last edited on
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.


Last edited on
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.
Last edited on
Topic archived. No new replies allowed.