Variable arguments for a Constructor

U

utab

Dear all,

How can I generate a constructor to take a variable number of
arguments. Is boost tuple appropriate for this?

I know that there is a way to make functions take variable number of
arguments, but that is not recommended. If I can not find another way,
I will apply that one.

Regards
 
G

gMorphus

utab said:
Dear all,

How can I generate a constructor to take a variable number of
arguments. Is boost tuple appropriate for this?

I know that there is a way to make functions take variable number of
arguments, but that is not recommended. If I can not find another way,
I will apply that one.

Regards

There is the usual way of adding ...
I don't know why it is not recommended, but you can always use
something of a list.
Even and STL::list, that contains structures like this:
struct PARAMETER {
PARAM_TYPE type;
void *data;
};
 
T

Thomas Tutone

utab said:
How can I generate a constructor to take a variable number of
arguments. Is boost tuple appropriate for this?

I know that there is a way to make functions take variable number of
arguments, but that is not recommended. If I can not find another way,
I will apply that one.

You can't use boost::tuple, because the tuple still needs to know how
many arguments there are. There may be some complicated way of using
template deduction to get around that problem, but it would probably be
more trouble than it's worth.

There are two recommended ways to accomplish what you want. The first
is to simply overload the constructor so that you have defined a
constructor for every possible number and type of arguments you intend
to use. The second is to pass one of the standard library's containers
(e.g., std::list, std::vector, etc) as as argument, and have that
container include all the arguments.

Best regards,

Tom
 
M

Markus Grueneis

utab said:
Dear all,

How can I generate a constructor to take a variable number of
arguments. Is boost tuple appropriate for this?

I know that there is a way to make functions take variable number of
arguments, but that is not recommended. If I can not find another way,
I will apply that one.

Regards

Maybe you could say what you _want_ to do, not how you think it should
be done. Maybe another design, or another C++ trick, would be more
appropriate. Otherwise, supplying a data-container (list, or some
simple data-only struct) would help. Also boost named parameters may be
appropriate, though I dislike them for their complexity. Tuples won't
help, as they have a fixed layout, and if you can find appropriate
default parameters for unsupplied arguments, you can do the same with
the constructor, or with simple structs (don't add depencies just
because it looks cool...).


best regards,
-- Markus
 
B

Bo Persson

gMorphus said:
There is the usual way of adding ...
I don't know why it is not recommended, but you can always use
something of a list.

It's more that it is a C-ism, what yo have to do when you can't
overload. A C++ class can have any number of constructors, with
different parameter types. They can even be templated, if you don't
know the types before hand.

Also, you can only pass PODs to ... anyway, so its usability is
limited.


Bo Persson
 
P

Pete Becker

utab said:
I know that there is a way to make functions take variable number of
arguments, but that is not recommended.

If it's the appropriate tool, use it. Far too many programmers spend far
too much time developing elaborate workarounds for things that someone
has told them are bad.
 
G

gMorphus

utab said:
Thank you but Can you give an example with this structure? I am a
little bit slow learner ;)

It's not too generic.. You can use the RTTI mechanism to identify your
types, or you can use some enum you create for specific types you want
to allow:

enum PARAM_TYPE {
INT_TYPE,
SHORT_TYPE,
DOUBLE_TYPE,
STRING_TYPE
};

and so on...

struct PARAMETER {
PARAM_TYPE type;
void *data;
};

than define a list type:
typedef std::list < PARAMETER > t_ParametersList;

class MyClass {
public:
MyClass ( t_ParametersList &params );
....
};

now you go over the list, using the type member of the struct you know
how to case the data member of it.
 
T

Thomas Tutone

Thomas said:
You can't use boost::tuple, because the tuple still needs to know how
many arguments there are. There may be some complicated way of using
template deduction to get around that problem, but it would probably be
more trouble than it's worth.

There are two recommended ways to accomplish what you want. The first
is to simply overload the constructor so that you have defined a
constructor for every possible number and type of arguments you intend
to use.

For example:

class Foo {
public:
Foo();
Foo(int i);
Foo(int i, int j);
Foo(int i1, int i2, int i3);
Foo(std::string s1, std::string s2);
Foo(std::string s1, std::string s2, std::string s3);
// etc. ...
};
The second is to pass one of the standard library's containers
(e.g., std::list, std::vector, etc) as as argument, and have that
container include all the arguments.

For example:

class Bar {
public:
Bar(const std::vector<int>& v);
};

std::vector<int> vec;
vec.push_back(1);
vec.push_back(5);
vec.push_back(-32);
Bar bar(vec);

Hope that helps.

Best regards,

Tom
 
U

utab

You can't use boost::tuple, because the tuple still needs to know how
many arguments there are. There may be some complicated way of using
template deduction to get around that problem, but it would probably be
more trouble than it's worth.

I got that
There are two recommended ways to accomplish what you want. The first
is to simply overload the constructor so that you have defined a
constructor for every possible number and type of arguments you intend
to use. The second is to pass one of the standard library's containers

I will supply the number of parameters first and then the parameters
must be pushed_back into a vector of parameters. sth like

ctor(int num_p,p1,p2,....)

for(int i=0;i!=num_p;++i)
params_vec.push_back(parameters)

params_vec is a data member of the class. Is there a way to get around
this.
 
U

utab

class Foo {
public:
Foo();
Foo(int i);
Foo(int i, int j);
Foo(int i1, int i2, int i3);
Foo(std::string s1, std::string s2);
Foo(std::string s1, std::string s2, std::string s3);
// etc. ...

This is not practical, I would like a more automated way
For example:

class Bar {
public:
Bar(const std::vector<int>& v);
};

std::vector<int> vec;
vec.push_back(1);
vec.push_back(5);
vec.push_back(-32);
Bar bar(vec);

Hope that helps.

Best regards,

Tom

This is another non automated way. Please see my post on what I try to
do on the ctor.

Regards,
 
F

Frederick Gotham

utab posted:
How can I generate a constructor to take a variable number of
arguments.

The same way with any other function:

#include <cassert>
#include <cstdarg>
#include <iostream>

using std::cout;

class MyClass {
public:

MyClass(char const *p,...)
{
assert(p); assert(*p);

va_list ap;
va_start(ap,p);

do
{
assert(*p == 'u' || *p == 'i' || *p == 'd' || *p == 's');

switch(*p)
{
case 'u': cout << va_arg(ap,unsigned) << '\n'; break;
case 'i': cout << va_arg(ap,int) << '\n'; break;
case 'd': cout << va_arg(ap,double) << '\n'; break;
case 's': cout << va_arg(ap,char const*) << '\n'; break;
}
}
while(*++p);
}
};

int main()
{
MyClass obj("isduds",-77,"Hello!",23948.352,88U,23.3,"Goodbye!");
}
 
M

Markus Grueneis

utab said:
[...]

I will supply the number of parameters first and then the parameters
must be pushed_back into a vector of parameters. sth like

ctor(int num_p,p1,p2,....)

for(int i=0;i!=num_p;++i)
params_vec.push_back(parameters)

params_vec is a data member of the class. Is there a way to get around
this.

Yes, you pass params_vec to the constructor.

ctor(const std::vector<ParamType> &params) : params_vec(params)
{}

ParamType must have a copy constructor. Please see also

http://www.parashift.com/c++-faq-lite/ctors.html


best regards,
-- Markus
 
J

Jens Theisen

Thomas said:
You can't use boost::tuple, because the tuple still needs to know how
many arguments there are. There may be some complicated way of using
template deduction to get around that problem, but it would probably be
more trouble than it's worth.

It's not complicated:

#include <vector>
#include <boost/tuple/tuple.hpp>

using namespace boost::tuples;
using namespace std;

struct X
{
template< typename Tuple >
X(Tuple const& tuple)
{
init(tuple);
}

private:
template< typename Head, typename Tail >
void init(cons< Head, Tail > const& cell)
{
m_ints.push_back(cell.get_head());

init(cell.get_tail());
}

void init(null_type null) { }

vector< int > m_ints;
};

int main()
{
X x = make_tuple(1, 2, 3);
}

It's not always the right thing to do, admittedly.

Jens
 
R

Roland Pibinger

Yes, you pass params_vec to the constructor.

ctor(const std::vector<ParamType> &params) : params_vec(params)
{}

The 'STL-way' is to pass iterators, e.g.

template <class Iter>
ctor (Iter begin, Iter end): params_vec (begin, end){}

Best wishes,
Roland Pibinger
 
M

Markus Grueneis

Roland said:
The 'STL-way' is to pass iterators, e.g.

template <class Iter>
ctor (Iter begin, Iter end): params_vec (begin, end){}

Thx, now I remember it.

Just for the OP:
This allows to pass ranges, not just whole collections. Additionally,
you can pass a range of vector<T> to the constructor of vector<Q> at
T != Q, *iff* Q can be converted to T.


thx,
-- Markus
 
D

Diego Martins

utab said:
Dear all,

How can I generate a constructor to take a variable number of
arguments. Is boost tuple appropriate for this?

I know that there is a way to make functions take variable number of
arguments, but that is not recommended. If I can not find another way,
I will apply that one.

Regards

what about the "named parameter idiom" described in the FAQ?

Diego Martins
 

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

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,144
Latest member
KetoBaseReviews
Top