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

K

KK

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
 
N

noel.yap

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
 
G

Gianni Mariani

KK said:
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

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

To all the classes you care about ?
....
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);

This would become:

_sum=evalsum();
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?

Not possible with standard C++.
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 ?

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
 
J

Jonathan Mcdougall

KK said:
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?
No.

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

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.
Also, little off topic but is there a way I can avoid using a delimiter
in the variable length arguments ?

Yes, don't use variable length arguments.


Jonathan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top