views:

99

answers:

5

I have a class, say

class AddElement{
    int a,b,c;
}

With methods to set/get a,b,c... My question is definitely a logic question - say I implement AddElement as follows:

int Value=1;
Value+=AddElement.get_a()+AddElement.get_b()+AddElement.get_b();

Now imagine I want to do the above except 'a,b,c' are now arrays, and instead of 'adding' I do scalar addition. At runtime sometimes I need 'a' but not 'b' or 'c', so I could rewrite as:

Value+=AddElement.get_a();

(Of course the += is overloaded to represent a scalar addition... and Value is the same size as a) - Other times I might only need b or c to be added etc...

Is there a way to go about selecting which elements, a,b,c, I want to initialize and later use at runtime? ( i.e. I don't want to malloc a huge array if I'm not going to use it).

In the end I need a class that has a,b,c and then methods that can operate on any combination of a,b, or c - having the user define what methods they need at runtime (via some kind of flag, or config file).

Currently I'm doing the following:

Value+=AddElement.get_a()*FlagA+AddElement.get_b()*FlagB+AddElement.get_c()*FlagC;

where FlagA=1 if you want to use 'a' in the addition or 0 if you don't want it to be included (The same for FlagB and FlagC). This is costly if the array 'a' is very large.

I'm probably just not thinking hard enough, but this problem has been bothering me. If you need me to better define the issue I will try, but I believe this is enough to get my point across.

Edit 2 I also forgot to add that I can't use any conditionals during the implementation of the addition (this is going to be used in a CUDA kernel and I can't have any thread diverngance - I was hoping to avoid mentioning CUDA since this is entirely a c++ question)

Edit 3 I believe what I need to do is use virtual functions. I want to call the function in the same manner, except have it execute a case specific function.

Edit 4 I would appreciate if someone took a look at my solution - maybe its too 'exotic' and there's a simpler method to accomplish the same end. Thanks for all the suggestions!

Edit 5 Thanks to another user I looked at the Strategic Design Pattern - and this is exactly the solution I used for this problem. I had never heard of that before and ended up rethinking a problem that has already been done (took a while for someone to mention something about it). So the solution: Determine Algorithm at Runtime = Strategic Design Pattern.

A: 

How about a std::vector of elements?

Problem spec is a bit unclear, to say the least, but I think that would work for you.

Cheers & hth.,

Alf P. Steinbach
I want to have code that only executes any combination of 'a','b', or 'c' for a method where value+=a+b+c if a,b,c are need. If a is not needed then I want value+=b+c, if b is not needed value+=a+c etc... but I would like to define this without conditional statements. Thanks for your response
Marm0t
+2  A: 

You provide your class with a method GetSumOfActiveElements that does just what the name says. You can make this class virtual and create subclasses for each scenario, or have the class manage the memory efficiently in some other way.

Space_C0wb0y
This looks like its on the right track, but how would I distinguish what the 'active elements' are? Would I need to create some kind of struct that has element 'isactive=true/false' and then another element int 'a' ? This again would involve some kind of conditional that I am trying to avoid.
Marm0t
If you are going to always work with a full-length list then you need some test to eliminate the ones you don't want. Replacing `if` with `mult by 1/0` to avoid conditionals works, but it's not clear to me that it's better - perhaps on CUDA this is preferred though.
Steve Townsend
@Steve, I still need to test which is faster, divergence or using a mask. CUDA hates divergence so I have a feeling the masking I'm doing is going to be faster. I'll post a topic about it maybe... Myself and some other researchers are interested in the implications.
Marm0t
+1  A: 

Does this rough outline of code work for you?

struct S{
    int getx() {return 0;}
    int gety() {return 0;}
    int getz() {return 0;}
};

int main(){
    int (S::*p[3])(); // allocate as per need
    p[0] = &S::getx;  // populate as per need at run time
    p[1] = &S::gety;
    p[2] = 0;

    int val = 1;
    S obj;

    int nCount = 0;

    while(p[nCount] != 0)
        val += (obj.*(p[nCount++]))();
}

EDIT 2: @Steve Townsend: That's right. I missed that conditional stuff.

How about this.

struct S{
    int getx() {return 0;}
    int gety() {return 0;}
    int getz() {return 0;}
    S(){}
    S(S &obj, int (S::*p)()){
        val += (obj.*p)();
    }
    static int val;
};

int S::val = 0;

int main(){
    S obj;
    S buf[] = {S(obj, &S::getx), S(obj, &S::gety)};  // the magic happens here in
                                                      // the constructor
}
Chubsdad
@Chubsdad - isn't `while` a conditional?
Steve Townsend
its similar, but I can't do a loop (oops sorry forgot to say that too) -- I think I may have figured it out though : )
Marm0t
@Steve Townsend: Oops!. I missed that conditional stuff. How about Edit2?
Chubsdad
This approach is good, But I need to be able to repeatedly call the function. Appreciate your example it works for the constraints I imposed (Under constrained my problem - although some people thought it was over constrained!).
Marm0t
+1  A: 

What about something like this?

vector<pair<int, bool>> values(3);
values[0].first = 1;
values[0].second = false;

values[1].first = 2;
values[1].second = true;

values[2].first = 3;
values[2].second = false;

int sum = values[0].first * values[0].second + 
          values[1].first * values[1].second + 
          values[2].first * values[2].second;

You could probably make this cleaner/extensible using functors and <algorithm>.

It's not clear to me why conditionals are a bad thing - multiplication will be more expensive I would think. Is this a CUDA limitation or idiosyncracy?

If you allowed conditionals you could make your vector member a class that encapsulated a value and an in-use flag, and use filtering algorithms to perform aggregation as required.

Steve Townsend
a conditional in CUDA is usually bad if it causes thread divergence (in my case it will). The case you posted is very similar to what I have implemented now - I can't use vector class due to the CUDA API limitations (I may be wrong about that).
Marm0t
@Marm0t - sounds to me like the CUDA limitations rule out more elegant solutions, then. Good luck.
Steve Townsend
+1  A: 

So I think I got it -

struct S{
    int x,y;
    bool needx,needy;
};

class AnyFunction {
    protected:
        S Vals;
        int TotalValue;
    public:
        virtual void SetValues(void) =0;
        virtual void AddValues(void) =0;
}

class ImplementationFunc1 : public AnyFunction {
    public:
    void SetValues(S * Vals) { S.x=Vals->xval; }
    void AddValues(void){ TotalValue+=Vals->x; }
}

class ImplementationFunc2 : public AnyFunction {
    public:
    void SetValues(S * Vals) {S.x=Vals->xval;S.y=Vals->yval;}
    void AddValues(void){ TotalValue+=(Vals->x+Vals->y); }
}

int main(){
S SVals;
AnyFunction * APointerToAnyFunction;
// read a file that says if we need either x or y
SVals.needx=true; // (i.e. read from file)
SVals.needy=false; // (read from file)

if(Svals.needx){
    SVals.x=Xfromfile;
    if (Svals.needy){
        ImplementationFunc2 Imp1;
        SVals.y=yfromfile;
        APointerToAnyFunction=&Imp1;
    }
    else{
        ImplementationFunc1 Imp2;
        APointerToAnyFunction=&Imp2;
   }
}
...
// blah set some values
...

// So now I can call the function the same way (i.e. the call is always the same, no matter what kind of addition it needs to do), but I have all
// the logic for the conditions done _outside_ the addition
APointerToAnyFunction->AddValues();

So that should basically do it! no I can use the call: "APointerToAnyFunction->AddValues()" To perform the addition. The implementation can be determined by flags at the beginning of the program, then I can write a different class for each condition that i need to satisfy, and then have my polymorphic class inherit the properties of the base class.

Sorry if I did not fully define my problem, or the statement was vague - I didn't really know exactly how to do what I was explaining, but knew it was possible. Is this the right way to go about this? Is there a more efficient way?

Thanks to all who responded. Of course when x and y are arrays, I dynamically allocate x and y when necessary...

Marm0t
I'll let you guys determine if this is an adequate solution, sorry I couldn't explain better. I'm using this to call CUDA kernels that change depending on boundary conditions (which are represented as arrays). I need to be flexible with my BC's so I have to have all the possible combinations done out (or at least the most common. If I create a .so I should avoid linking with the unnecessary classes at runtime right - or can the compiler not determine if it actually needs all the classes until execution(I'm guessing the latter)?
Marm0t
This is something similar to the Strategy design pattern. I did not intentionally propose this as it is not very scalable if we have more than three to be added for eg. a, b, c, d, e, f and so on. The base class 'X' will not be able to handle it. The solution I proposed is much more generic. But anyway, good if your solution works for you!!.
Chubsdad
Ah yes I just looked at the Strategy design pattern! Should probably take more courses in programming and algoritms (an aero BS is pretty useless for programming...)
Marm0t