On Mar 21, 2015, at 6:09 AM, David Chisnall <[email protected]> wrote:
> On 20 Mar 2015, at 19:39, Scott Christley <[email protected]> wrote: >> >> Hello, >> >> This is more a generic Objective-C question versus GNUstep but maybe some >> experts here have a suggestion. >> >> I have a bunch of code that looks l like this: >> >> >> if ([encode isEqual: [BioSwarmModel floatEncode]]) { >> // interpret as float matrix >> float (*grid)[height][width] = matrix; >> for (i = 0;i < height; ++i) >> for (j = 0;j < width; ++j) >> (*grid)[i][j] = 0.0; >> >> } else if ([encode isEqual: [BioSwarmModel doubleEncode]]) { >> // interpret as double matrix >> double (*grid)[height][width] = matrix; >> for (i = 0;i < height; ++i) >> for (j = 0;j < width; ++j) >> (*grid)[i][j] = 0.0; >> } >> >> >> where I have a generic pointer void *matrix to some data, that I need to >> interpret as a specific data type, generally either int, float or double. >> The part I don’t like is that the operation is essentially identical >> regardless of the data type, but I have to duplicate code in order to handle >> it. In this example, the code is just zero’ing out the data. This can be a >> pain for more complicated operations as I have to make sure I do the correct >> changes to each code piece. What I would like is just to write the code >> once and have the compiler or whatever handle the data type for me: >> >> for (i = 0;i < height; ++i) >> for (j = 0;j < width; ++j) >> (*grid)[i][j] = 0.0; >> >> So is there some new Objective-C feature that I’m unaware of which can do >> this for me? > > This sounds like a job for Objective-C++. You'd write something like: > > template<typename T> > void zero(T *grid, size_t width, size_t height) > { > for (i = 0;i < height; ++i) > for (j = 0;j < width; ++j) > (*grid)[i][j] = (T)0; > } > > And then: > > if ([encode isEqual: [BioSwarmModel floatEncode]]) { > zero((float*)matrix, width, height); > } else if ([encode isEqual: [BioSwarmModel doubleEncode]]) { > zero((double*)matrix, width, height); > } > Very nice, that’s pretty close to what I was thinking. I will give that a try! > Although, in this specific case, you'd actually just want to do > bzero(height*width*sizeof(T)). Use Objective-C for the introspection and C++ > for the generic code. Oh, and it appears that you're reimplementing part of > the core Objective-C language here. You might look at @encode(). For > primitive types, all of the type encodings are single chars, so you can do a > simple switch, like this: > > switch(encoding) > { > case @encode(double)[0]: > zero((double*)matrix, width, height); > case @encode(float)[0]: > zero((float*)matrix, width, height); > } That’s a nice trick! Not sure why @encode was encapsulated like that, probably there was the thought that more advanced types would be used but never materialized. > When doing this kind of thing a lot, I generally wrap it in a macro. Take a > look at type_encoding_cases in libobjc2. You'd simplify this code to: > > switch(encoding) > { > #define APPLY_TYPE(type, name, capitalizedName, encodingChar) \ > case encodingChar: > zero((type*)matrix, width, height); > #include "type_encoding_cases.h" > } > I’ll take a look, thanks! Scott
_______________________________________________ Discuss-gnustep mailing list [email protected] https://lists.gnu.org/mailman/listinfo/discuss-gnustep
