Avoiding Copy-Paste code initialising a series of SDL_Rects in a Struct

I've got a struct for defining the graphics of a feature in my 2D engine. In that, there are a series of SDL_Rects called "middle, left_edge, top_left_corner" etc. In part of my code, I'm initialising them off a series of arguments types into the scripting engine/command line, that are stored as a vector of std::strings.

As a matter of style, and avoiding stupid mistakes due to repetition (and having to correct any mistakes 9 times), is there any way to clean up this code? Or would this be reasonable?

//RectZeroes is just an SDL_Rect of {0,0,0,0} to ensure that it is initialised SDL_Rect middle = RectZeroes; if (args.size() >= 6 ) { middle.x = boost::lexical_cast<int>(args[3]); middle.y = boost::lexical_cast<int>(args[4]); middle.w = boost::lexical_cast<int>(args[5]); middle.h = boost::lexical_cast<int>(args[6]); } SDL_Rect left_edge = RectZeroes; if (args.size() >= 10 ) { left_edge.x = boost::lexical_cast<int>(args[7]); left_edge.y = boost::lexical_cast<int>(args[8]); left_edge.w = boost::lexical_cast<int>(args[9]); left_edge.h = boost::lexical_cast<int>(args[10]); } //And so on

-------------Problems Reply------------

I agree that this isn’t a pleasant code. To avoid the repetition, do the same as always in programming: encapsulate – in this case, encapsulate the structure and giving it a proper constructor, and write a thin wrapper around boost::lexical_cast<int>(x).

Or, if you want to avoid wrapping SDL_Rect then write an initialiser function:

template <typename TString>
int parse_int(TString const& value) { return boost::lexical_cast<int>(value); }

void init_sdl_rect_from_args(
SDL_Rect& rect, std::vector<std::string> const& args, unsigned offset)
{
rect.x = parse_int(args[offset + 0]);
rect.y = parse_int(args[offset + 1]);
rect.w = parse_int(args[offset + 2]);
rect.h = parse_int(args[offset + 3]);
}

And then:

SDL_Rect middle = RectZeroes;
if (args.size() >= 6)
init_sdl_rect_from_args(middle, args, 3);

SDL_Rect left_edge = RectZeroes;
if (args.size() >= 10)
init_sdl_rect_from_args(left_edge, args, 7);

Better yet, make the initialiser return the constructed structure. This makes it even more convenient to use (namely, in an initialiser):

SDL_Rect rect_from_args(std::vector<std::string> const& args, unsigned offset) {
SDL_Rect rect;
rect.x = parse_int(args[offset + 0]);
rect.y = parse_int(args[offset + 1]);
rect.w = parse_int(args[offset + 2]);
rect.h = parse_int(args[offset + 3]);
return rect;
}

SDL_Rect middle = (args.size() >= 6) ? rect_from_args(args, 3) : RectZeroes;
SDL_Rect left_edge = (args.size() >= 10) ? rect_from_args(args, 7) : RectZeroes;

Category:c# Views:1 Time:2012-02-13
Tags: boost sdl

Related post

Copyright (C) dskims.com, All Rights Reserved.

processed in 0.127 (s). 11 q(s)