Connecting Tech Pros Worldwide Help | Site Map

Passing speicifc class elements as arguments without explicitly listing them - is it possible?

  #1  
Old December 2nd, 2005, 01:15 AM
KK
Guest
 
Posts: n/a
Hello all,
I have several classes binded by one common interface - say 'sum'
interface which calculates the sum of all the class elements of type
'int'.

class Alphabet
{
int _a;
int _b;
int _c;
char _ch; // some other stray element
friend double sumInterface( int first, ... );
public:
double _sum; // ' double' type introduced to differentiate from above
core elements
Alphabet( void)
{
_a=_b=_c=2;
_sum=sumInterface(_a,_b,_c,-1);
}
};

class Numbers
{
int _one;
int _two;
friend double sumInterface( int first, ... );
public:
double _sum;
Numbers(void)
{
_one=1;
_two=2;
_sum=sumInterface(_one,_two,-1);
}
};

double sumInterface( int first, ... )
{
int i = first;
double sum=0;
va_list marker;
va_start( marker, first ); /* Initialize variable arguments. */
while( i != -1 ) //-1 acts as delimiter
{
sum += i;
i = va_arg( marker, int);
}
va_end( marker ); /* Reset variable arguments. */
return sum ;
}

The problem with this approach is that I need to provide all the class
elements to this function each type I invoke it.

_sum=sumInterface(_a,_b,_c,-1);
_sum=sumInterface(_one,_two,-1);

Is there anyway I make the function to understand to consider all the
class elements of type int so that I dont have to explicitly type all
the elements?

If yes, can I general this concept to other user defined data types?

Also, little off topic but is there a way I can avoid using a delimiter
in the variable length arguments ?

Thank you.
-KK

  #2  
Old December 2nd, 2005, 02:35 AM
noel.yap@gmail.com
Guest
 
Posts: n/a

re: Passing speicifc class elements as arguments without explicitly listing them - is it possible?


I don't see any way to do this in C++. OTOH, you might be able to use
SWIG to sort of reflect upon your class, generating XML, then generate
the code you need by parsing the XML.

Noel

  #3  
Old December 2nd, 2005, 08:15 AM
Gianni Mariani
Guest
 
Posts: n/a

re: Passing speicifc class elements as arguments without explicitly listing them - is it possible?


KK wrote:[color=blue]
> Hello all,
> I have several classes binded by one common interface - say 'sum'
> interface which calculates the sum of all the class elements of type
> 'int'.
>
> class Alphabet
> {
> int _a;
> int _b;
> int _c;
> char _ch; // some other stray element[/color]

Why not just add a method:
double evalsum()
{
return sumInterface(_a,_b,_c,-1);
}

To all the classes you care about ?
....[color=blue]
>
> The problem with this approach is that I need to provide all the class
> elements to this function each type I invoke it.
>
> _sum=sumInterface(_a,_b,_c,-1);
> _sum=sumInterface(_one,_two,-1);[/color]

This would become:

_sum=evalsum();
[color=blue]
>
> Is there anyway I make the function to understand to consider all the
> class elements of type int so that I dont have to explicitly type all
> the elements?[/color]

Not possible with standard C++.
[color=blue]
>
> If yes, can I general this concept to other user defined data types?
>
> Also, little off topic but is there a way I can avoid using a delimiter
> in the variable length arguments ?[/color]

Use overloaded functions.

double sum( int v1 )
{
return double(v1);
}

double sum( int v1, int v2 )
{
return double(v1) + v2;
}

double sum( int v1, int v2, int v3 )
{
return double(v1) + v2 + v3;
}

....

To as many as you care about

  #4  
Old December 2nd, 2005, 08:45 AM
Jonathan Mcdougall
Guest
 
Posts: n/a

re: Passing speicifc class elements as arguments without explicitly listing them - is it possible?


KK wrote:[color=blue]
> Hello all,
> I have several classes binded by one common interface - say 'sum'
> interface which calculates the sum of all the class elements of type
> 'int'.
>
> class Alphabet
> {
> int _a;
> int _b;
> int _c;
> char _ch; // some other stray element
> friend double sumInterface( int first, ... );
> public:
> double _sum; // ' double' type introduced to differentiate from above
> core elements
> Alphabet( void)
> {
> _a=_b=_c=2;
> _sum=sumInterface(_a,_b,_c,-1);
> }
> };
>
> class Numbers
> {
> int _one;
> int _two;
> friend double sumInterface( int first, ... );
> public:
> double _sum;
> Numbers(void)
> {
> _one=1;
> _two=2;
> _sum=sumInterface(_one,_two,-1);
> }
> };
>
> double sumInterface( int first, ... )
> {
> int i = first;
> double sum=0;
> va_list marker;
> va_start( marker, first ); /* Initialize variable arguments. */
> while( i != -1 ) //-1 acts as delimiter
> {
> sum += i;
> i = va_arg( marker, int);
> }
> va_end( marker ); /* Reset variable arguments. */
> return sum ;
> }
>
> The problem with this approach is that I need to provide all the class
> elements to this function each type I invoke it.
>
> _sum=sumInterface(_a,_b,_c,-1);
> _sum=sumInterface(_one,_two,-1);
>
> Is there anyway I make the function to understand to consider all the
> class elements of type int so that I dont have to explicitly type all
> the elements?[/color]

No.
[color=blue]
> If yes, can I general this concept to other user defined data types?[/color]

Depending on your design, you may be better with containers. These
classes seem like container-like classes, so you could either

1) typedef them to standard containers

typedef std::vector<int> Alphabet;
typedef std::vector<int> Numbers;

void f(Alphabet &a)
{
int sum = std::accumulate(a.begin(), a.end(), 0);
}

2) use standard containers internally and provide a (standard if
possible) container interface

class Alphabet
{
public:
typedef Cont::iterator iterator;

iterator begin()
{
return cont_.begin();
}

iterator end()
{
return cont_.end();
}

private:
typedef std::vector<int> Cont;
Cont cont_;
};

void f(Alphabet &a)
{
// note: this does not change
int sum = std::accumulate(a.begin(), a.end(), 0);
}

3) Return a container from a member function containing all the values.
That would fit if the class is not really a container. This would wrap
all the values in a container to calculate the sum (or something else)
easily.

class Alphabet
{
public:
typedef std::vector<int> Container;

Container cont() const
{
Container c;
c.push_back(a_);
c.push_back(b_);

return c;
}

private:
int a_, b_;
};

4) Use the sum computed by a member function, which removes the need
for "do-it-all" free function

class Alphabet
{
public:
int sum() const
{
return a_ + b_;
}

private:
int a_, b_;
};

void f(Alphabet &a)
{
int sum = a.sum();
}


You may use inheritance or templates if you need to work with multiple
classes. For example, f() could be rewritten as

template <class C>
int sum(C &c)
{
int sum = std::accumulate(c.begin(), c.end(), 0);

// or

int sum = c.sum();
}

As you see, you are not short of options.
[color=blue]
> Also, little off topic but is there a way I can avoid using a delimiter
> in the variable length arguments ?[/color]

Yes, don't use variable length arguments.


Jonathan

Closed Thread