Help with functor/template/constructor

Discussion in 'C++' started by jack, Feb 23, 2004.

  1. jack

    jack Guest

    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;

    }
     
    jack, Feb 23, 2004
    #1
    1. Advertising

  2. jack wrote:
    > ...
    > 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.

    --
    Best regards,
    Andrey Tarasevich
     
    Andrey Tarasevich, Feb 24, 2004
    #2
    1. Advertising

  3. jack

    jack Guest

    "Andrey Tarasevich" <> wrote in message
    news:...

    Thank you very much for your detailed explanation!

    Jack
     
    jack, Feb 24, 2004
    #3
  4. "jack" <> wrote...
    > 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
     
    Victor Bazarov, Feb 28, 2004
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chandra Shekhar Kumar

    functor object in template class

    Chandra Shekhar Kumar, Jun 24, 2003, in forum: C++
    Replies:
    5
    Views:
    1,283
    porschberg
    Jun 26, 2003
  2. CoolPint
    Replies:
    3
    Views:
    722
    tom_usenet
    Dec 29, 2003
  3. Replies:
    8
    Views:
    408
  4. Generic Usenet Account
    Replies:
    10
    Views:
    2,282
  5. Dijkstra
    Replies:
    12
    Views:
    634
    gpderetta
    Jul 10, 2008
Loading...

Share This Page