By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,130 Members | 2,228 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,130 IT Pros & Developers. It's quick & easy.

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

P: n/a
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

Dec 2 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
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

Dec 2 '05 #2

P: n/a
KK wrote:
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

Dec 2 '05 #3

P: n/a
KK wrote:
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

Dec 2 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.