Help with functor/template/constructor

J

jack

Hi there,

I have a function F(x, y, z)
and I want to calculate f(a) + f(b), where f(x) = F(x, x, z0)
z0 is fixed.

Suppose somebody wrote a routine called "Compute" which simply
computes f(a) + f(b) for any one dimensional function f.

Then I create a f1dim which converts any n-dimensional function
G to a one dimensional f(x) = G(x, x, ..., x), via a class
Three_To_One which suppresses (fixes) 1) dimension and 2) function G
in f's argument list.

Also create a class Three_To_Vec which fixes parameter z
in my origional function F, and make it look like a function
with a single array/pointer parameter, i.e., H(w[]) = F(w[0], w[1], z0).

1) If I do not provide a default constructor in Three_To_Vec,
the program won't compile. Why?

2) Why are the destructors of both classes (Three_To_One and Three_To_Vec)
called multiple times, while the constructors are only called once?

Thank you for your help.

Jack

========================== source code in a single file ==================


#include <iostream>
using namespace std;


/* ================= Original function ================== */

double my_3d_f(double x, double y, double z)
{
return x*x*x + 2.0*x*y + 3.0*x*z + x + 3.0*z + 6.0;
}

/* ================= Two Classes used in Functor ============= */

template <class T>
class Three_To_One
{
public:
double (*m_f)(double, int, T);
int m_p1;
T m_p2;

Three_To_One(double(*f)(double, int, T), int p1, T p2)
{
cout << " 3-to-1: c-tor" << endl;
m_f=f;
m_p1=p1;
m_p2=p2;
}

~Three_To_One() { cout << " 3-to-1: D-tor" << endl; }

double operator()(double x)
{
return m_f(x, m_p1, m_p2);
}
};


class Three_To_Vec
{
public:
double (*m_f)(double, double, double);
double m_p;

Three_To_Vec()
{
cout << "3-to-V: default" << endl;
}

Three_To_Vec(double(*f)(double, double, double), double p)
{
cout << "3-to-V: c-tor" << endl;
m_f = f;
m_p = p;
}

~Three_To_Vec() { cout << "3-to-V: D-tor" << endl; }

double operator()(double theta[])
{
return m_f(theta[0], theta[1], m_p);
}
};

/* ========== Somebody's function to compute f(a) + f(b) =================== */

template <class T>
double Compute(T f, double a, double b)
{
return f(a) + f(b);
}

/* ========== Convert n-dimensional to 1-dimensional ================= */

template <class T>
double f1dim(double t, int n, T fnd)
{
int j;
double fval, *x;

x = new double[n];
for(j=0; j < n; ++j)
x[j] = t;
fval = fnd(x);
delete []x;
return fval;
}

/* =========== My function to compute F(a,a,z0) + F(b, b, z0) =================== */

template <class T>
double Go(T fnv, int n, double a, double b)
{
return Compute(Three_To_One<T>(f1dim, n, fnv), a, b);
}


int main()
{

double result;

result = Go(Three_To_Vec(my_3d_f, 3.14159), 3, 2.0, 9.0);
// compute F(2, 2, pi) + F(9, 9, pi)

cout << "result = " << result << endl;

return 0;

}
 
A

Andrey Tarasevich

jack said:
...
1) If I do not provide a default constructor in Three_To_Vec,
the program won't compile. Why?

In your program you instantiate function template 'Go<T>' with deduced
template parameter 'T' equal to 'Three_To_Vec'. This instance of
function template 'Go' in turn will instantiate class template
'Three_To_One<T>' with template parameter 'T' equal to 'Three_To_Vec'.
Now if you look closely you'll see that class template 'Three_To_One<T>'
has a data member named 'm_p2' of type 'T' (which is 'Three_To_Vec' in
our case). This data member is default-constructed, since you don't
mention it in 'Three_To_One<T>'s constructor initializer list. That's
why the compiler needs default constructor for 'Three_To_Vec'.

Maybe you should copy-construct that 'm_p2' (an all other data members)
in 'Three_To_One<T>'s constructor instead of assigning to it:

Three_To_One(double(*f)(double, int, T), int p1, T p2) :
m_f(f), m_p1(p1), m_p2(p2)
{
cout << " 3-to-1: c-tor" << endl;
}

In this case the compiler won't ask for default constructor in
'Three_To_Vec'.
2) Why are the destructors of both classes (Three_To_One and Three_To_Vec)
called multiple times, while the constructors are only called once?

You forgot to count copy-constructor calls. Since you didn't declare any
copy-constructors in your classes, the compiler declared (and defined)
them implicitly. These implicitly defined copy-constructors don't output
anything into 'cout', which prevents you from noticing these calls.
 
V

Victor Bazarov

jack said:
I have a function F(x, y, z)
and I want to calculate f(a) + f(b), where f(x) = F(x, x, z0)
z0 is fixed.

Suppose somebody wrote a routine called "Compute" which simply
computes f(a) + f(b) for any one dimensional function f.

Then I create a f1dim which converts any n-dimensional function
G to a one dimensional f(x) = G(x, x, ..., x), via a class
Three_To_One which suppresses (fixes) 1) dimension and 2) function G
in f's argument list.

Also create a class Three_To_Vec which fixes parameter z
in my origional function F, and make it look like a function
with a single array/pointer parameter, i.e., H(w[]) = F(w[0], w[1], z0).

1) If I do not provide a default constructor in Three_To_Vec,
the program won't compile. Why?

Could it be because it's needed. Have you run your program? If I do,
I see output that indicates that the default c-tor for Three_To_Vec is
called. I'll leave it to you to find out where.
2) Why are the destructors of both classes (Three_To_One and Three_To_Vec)
called multiple times, while the constructors are only called once?

Because there are copy constructors called that you don't register.

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

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top