class problem

P

Patrick Guio

Dear all,

I wonder whether there is simple way to do the following.
I have a class A which the default constructor takes an integer as
argument:
A a(2);
Now I create an object of class A at compilation time (I now the integer
value only at run-time)
What I would like to do is to define a class B that behaves like the
object of class A created with an integer value at run time
but which creator does not take any argument.

Something like

int main(int nargs, char *args[])
{
A a(nargs);

B b;
}

where b would actually be the same as a(nargs).


Sincerely,
Patrick
 
J

John Harrison

Patrick Guio said:
Dear all,

I wonder whether there is simple way to do the following.
I have a class A which the default constructor takes an integer as
argument:
A a(2);
Now I create an object of class A at compilation time (I now the integer
value only at run-time)
What I would like to do is to define a class B that behaves like the
object of class A created with an integer value at run time
but which creator does not take any argument.

Something like

int main(int nargs, char *args[])
{
A a(nargs);

B b;
}

where b would actually be the same as a(nargs).

The only way I can think of would be to use some sort of global variable to
create the connection between a and b behind the scenes. But why in God's
name would you want to do something as obscure as that.

You don't say why you need this, but I'm sure there must be a better way.
Probably you've misunderstood something and think you really need this.
Almost certainly you are mistaken.

john
 
R

Ron Natalie

Patrick said:
where b would actually be the same as a(nargs).

You could store the nargs value in a static member of A and
use that in B's default constructor.


class A {
public:
A(int n) : nargs(n) {
static_nargs = n;
}
protected:
int nargs;
static int nargs;
};
int A::static_nargs = 0;

class B : public A {
public:
B() : A(static_nargs) { }
};
 
R

Ron Natalie

Ron said:
You could store the nargs value in a static member of A and
use that in B's default constructor.


class A {
public:
A(int n) : nargs(n) {
static_nargs = n;
}
protected:
int nargs;
static int nargs; static int static_nargs;
};
int A::static_nargs = 0;

class B : public A {
public:
B() : A(static_nargs) { }
};
 
V

Victor Bazarov

Ron said:
static int static_nargs;


It really depends on the definition of "the same" in the OP's message,
doesn't it? In your code, "the same" means something like "compares
equal", while it _might_ mean "referring to the same object". To do
that, one would need some kind of global reference transfer.

IOW, not enough information in the original post.

V
 
P

puppet_sock

Patrick Guio said:
Dear all,

I wonder whether there is simple way to do the following.
I have a class A which the default constructor takes an integer as
argument:
A a(2);

The default ctor does not take any arguments.
Now I create an object of class A at compilation time (I now the integer
value only at run-time)

No, you don't create any objects at compile time. No objects
exist until you run the program.
What I would like to do is to define a class B that behaves like the
object of class A created with an integer value at run time
but which creator does not take any argument.

Something like

int main(int nargs, char *args[])
{
A a(nargs);

B b;
}

where b would actually be the same as a(nargs).

Actually, your problem is you have not fully specified the requirements.
What do you mean by "behaves like the object of class A" anyway?
For example, if you replaced the B b; line with

A & rA = a;

you would have a reference to the object a, and you could treat rA as
an alias for the object a. If that what you wanted? What exactly is it
you wanted? What are you trying to accomplish?

Many times folks will come on here and ask "how do I do <insert
abstruse thing that's difficult or impossible in C++>" and get
upset when people tell them not to do that. It's usually because
they want to accomplish some end task, and have ceased upon some
thing they think will make it easy. But in reality, the end task
is actually easy using some standard pattern in C++.

So, what's your end task?
Socks
 
S

Stuart Gerchick

Patrick Guio said:
Dear all,

I wonder whether there is simple way to do the following.
I have a class A which the default constructor takes an integer as
argument:
A a(2);
Now I create an object of class A at compilation time (I now the integer
value only at run-time)
What I would like to do is to define a class B that behaves like the
object of class A created with an integer value at run time
but which creator does not take any argument.

Something like

int main(int nargs, char *args[])
{
A a(nargs);

B b;
}

where b would actually be the same as a(nargs).


Sincerely,
Patrick

are you allowed to simply say

b=a;

where you have in b an assignment operator that takes care of it for you?
 
P

Patrick Guio

I guess that would do what I need in a way.
It really depends on the definition of "the same" in the OP's message,
doesn't it? In your code, "the same" means something like "compares
equal", while it _might_ mean "referring to the same object". To do
that, one would need some kind of global reference transfer.

More details....
I have defined a function template that takes a class with a method op()
and bench it. Shortly something like

template <class C>
void benchmark(double minTime)
{
C c;
Timer timer;
double oneOpTime;
double totalTime;
int ni = 1;
do
{
timer.start();
for (int i = 0; i < ni; i++) c.op();
timer.stop();
oneOpTime = (totalTime=(timer.userElapsed())) / ni;
ni <<= 1;
} while (totalTime < minTime);

std::cout << "time for one op()" << smartTime(avOneOpTime) << std::endl;
}

So with a class definition

class C
{
C();
void op();
}

then I can write for example
benchmark<C>(1.0);

But what about a class with definition
class C
{
C(int n);
void op();
}

I cannot write
benchmark<C(2)>(1.0);

How do I solve that?

Sincerely, Patrick
 
V

Victor Bazarov

Patrick said:
I guess that would do what I need in a way.



More details....
I have defined a function template that takes a class with a method op()
and bench it. Shortly something like

template <class C>
void benchmark(double minTime)
{
C c;
Timer timer;
double oneOpTime;
double totalTime;
int ni = 1;
do
{
timer.start();
for (int i = 0; i < ni; i++) c.op();
timer.stop();
oneOpTime = (totalTime=(timer.userElapsed())) / ni;
ni <<= 1;
} while (totalTime < minTime);

std::cout << "time for one op()" << smartTime(avOneOpTime) << std::endl;
}

So with a class definition

class C
{
C();
void op();
}

then I can write for example
benchmark<C>(1.0);

But what about a class with definition
class C
{
C(int n);
void op();
}

I cannot write
benchmark<C(2)>(1.0);

How do I solve that?

Why don't you pass the object as an argument?

template<class C> void benchmark(const C& c, double minTime)
{
...
}

The requirement is that your class' 'op' member function will have to
be 'const':

class C {
public:
C(int);
void op() const;
};

Then you just call it like this:

benchmark(C(2), 1.0);

Of course, if you _have_ to have a non-const member function 'op', then
you will be forced to create a real object and pass it into the function:

C c(2);
benchmark(c, 1.0);

Victor
 
J

John Harrison

Patrick Guio said:
I guess that would do what I need in a way.


More details....
I have defined a function template that takes a class with a method op()
and bench it. Shortly something like

template <class C>
void benchmark(double minTime)
{
C c;
Timer timer;
double oneOpTime;
double totalTime;
int ni = 1;
do
{
timer.start();
for (int i = 0; i < ni; i++) c.op();
timer.stop();
oneOpTime = (totalTime=(timer.userElapsed())) / ni;
ni <<= 1;
} while (totalTime < minTime);

std::cout << "time for one op()" << smartTime(avOneOpTime) << std::endl;
}

So with a class definition

class C
{
C();
void op();
}

then I can write for example
benchmark<C>(1.0);

But what about a class with definition
class C
{
C(int n);
void op();
}

I cannot write
benchmark<C(2)>(1.0);

How do I solve that?

Sincerely, Patrick

Is there any reason not to use a parameter to pass the object to the
benchmark routine.

template <class C>
void benchmark(C& c, double minTime)
{

seems the obvious thing to do.

If that is not acceptable for some reason then you could pass the
constructor parameters to benchmark.

This would work for any C that has a one parameter constructor

template <class C, class T>
void benchmark(const T& t, double minTime)
{
C c(t);
...

and this for any two parameters

template <class C, class T, class U>
void benchmark(const T& t, const U& u, double minTime)
{
C c(t, u);
...

Anything seems preferable to what you are proposing.

john
 
P

Patrick Guio

Why don't you pass the object as an argument?

template<class C> void benchmark(const C& c, double minTime)
{
...
}

The requirement is that your class' 'op' member function will have to
be 'const':

class C {
public:
C(int);
void op() const;
};

Then you just call it like this:

benchmark(C(2), 1.0);

Of course, if you _have_ to have a non-const member function 'op', then
you will be forced to create a real object and pass it into the function:

C c(2);
benchmark(c, 1.0);

Thank you Victor,

It works very nicely when member function 'op' is const as you pointed
out. I have unfortunately a case where I cannot declare 'op' as const
member function since I am modifying a member field value.
But then I get a compiler error even though I create a real object before
passing it into the function as you proposed.

c++-tools/bench.h:26: error: passing `const test2' as `this' argument of `void
test2::eek:p()' discards qualifiers

Any idea of how to remedy?

Sincerely,

Patrick
 
P

Patrick Guio

This would work for any C that has a one parameter constructor

template <class C, class T>
void benchmark(const T& t, double minTime)
{
C c(t);
...

and this for any two parameters

template <class C, class T, class U>
void benchmark(const T& t, const U& u, double minTime)
{
C c(t, u);
...

John,

Would there be a more generic way to handle one, two, ... as many
parameters to avoid having to cut-and-paste the template function?

Sincerely,
Patrick
 
J

John Harrison

Patrick Guio said:
John,

Would there be a more generic way to handle one, two, ... as many
parameters to avoid having to cut-and-paste the template function?

Sincerely,
Patrick

The only way I know is with tricks using the preprocessor. Have a look at
the boost preprocessor library,
http://www.boost.org/libs/preprocessor/doc/index.html. The very first topic
'motivation' discusses your situation.

Whether all this is preferable to the cut and paste solution is highly
debatable though I think.

john
 
V

Victor Bazarov

Patrick said:
Thank you Victor,

It works very nicely when member function 'op' is const as you pointed
out. I have unfortunately a case where I cannot declare 'op' as const
member function since I am modifying a member field value.
But then I get a compiler error even though I create a real object
before passing it into the function as you proposed.

c++-tools/bench.h:26: error: passing `const test2' as `this' argument of
`void
test2::eek:p()' discards qualifiers

Any idea of how to remedy?

There is only one remedy I can think of. If your 'benchmark' function
will take the 'C' argument by value:

template<class C> void benchmark(C c, double minTime) { ...

then inside you may call its non-const member. Of course, that might
cause some extra copying as the result.

Victor
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
474,183
Messages
2,570,967
Members
47,516
Latest member
ChrisHibbs

Latest Threads

Top