discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: data type polymorphism


From: Scott Christley
Subject: Re: data type polymorphism
Date: Mon, 23 Mar 2015 10:37:47 -0500


On Mar 21, 2015, at 6:09 AM, David Chisnall <theraven@sucs.org> wrote:

On 20 Mar 2015, at 19:39, Scott Christley <schristley@mac.com> 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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]