A mess with inheritance, virtual classes , and templates.

Discussion in 'C++' started by cesarth, Oct 28, 2011.

  1. cesarth

    cesarth Guest

    Hello all,

    I have a code that works without templating and when I apply templates
    doesn't.
    I tried to simplify it as much as possible, but it is a little long.

    This code works without templating:

    //*****************************************************************
    #include <iostream>
    #include <cmath> // exp

    using namespace std;

    struct basf{
    virtual double eval(void) const{ cerr << "ERROR: base
    class()"<<endl; };
    };
    ostream& operator<<(ostream &os, const basf & bas){ os<< bas.eval();
    return os; };

    struct vfoo: public basf{
    double * var;
    vfoo( double * v, const string &rep1 ): var(v), rep(rep1){};
    void operator=( const double & v ) { *var=v; };
    // operator foo( ){ foo fun(this); return fun; };
    // operator foo&( ){ foo fun(this); return fun; };
    double eval() const{ return *var; };
    };
    struct foo{
    basf *fp;
    foo( basf * pbfun ) : fp(pbfun) { };
    foo( vfoo &vx ) : fp(&vx) { };
    // foo( ) { };
    double eval(void) const{ return fp->eval(); };
    };

    struct efoo: public basf{
    foo sub;
    efoo( foo sf ) : sub(sf) {};
    operator foo( ){ foo fun(this); return fun; };
    double eval() const{ return exp( sub.eval() ); };
    };

    efoo exp3( foo sf ) { return efoo( sf ); };

    void testfun2(void){
    double x=14.10;
    vfoo vx(&x,"x");
    cout << "vx = " << vx << endl;
    foo f1=vx;
    cout <<" f1.eval() = "<< f1.eval() << endl;
    foo f2= efoo(vx);
    cout <<" f2.eval() = "<< f2.eval() << endl;
    foo f3= exp3(f1);
    cout <<" f3.eval() = "<< f3.eval() << endl;
    }
    int main( int argc, char** argv, char** envp){
    testfun2();
    return 0;
    }
    //*****************************************************************

    But doesn't with templates:

    //*****************************************************************
    #include <iostream>
    #include <cmath> // exp

    using namespace std;

    template <class T> struct basf{
    virtual T eval(void) const{ cerr << "ERROR: base class()"<<endl; };
    };
    template<class T> ostream& operator<<(ostream &os, const basf<T> & bas)
    { os<< bas.eval(); return os; };

    template <class T> struct vfoo: public basf<T>{
    T * var;
    vfoo( T * v, const string &rep1 ): var(v), rep(rep1){};
    void operator=( const T & v ) { *var=v; };
    // operator foo<T>( ){ foo<T> fun(this); return fun; };
    // operator foo<T>&( ){ foo<T> fun(this); return fun; };
    T eval() const{ return *var; };
    };
    template <class T> struct foo{
    basf<T> *fp;
    foo( basf<T> * pbfun ) : fp(pbfun) { };
    foo( vfoo<T> &vx ) : fp(&vx) { };
    // foo( ) { };
    T eval(void) const{ return fp->eval(); };
    };
    template <class T> struct efoo: public basf<T>{
    foo<T> sub;
    efoo( foo<T> sf ) : sub(sf) {};
    operator foo<T>( ){ foo<T> fun(this); return fun; };
    T eval() const{ return exp( sub.eval() ); };
    string str(void) const { return "exp("; };
    };

    template <class T> efoo<T> exp3( foo<T> sf ) { return
    efoo<T>( sf ); };

    void testfun2(void){
    double x=14.10;
    vfoo<double> vx(&x,"x");
    cout << "vx = " << vx << endl;
    foo<double> f1=vx;
    cout <<" f1.eval() = "<< f1.eval() << endl;
    foo<double> f2= efoo<double>(vx);
    cout <<" f2.eval() = "<< f2.eval() << endl;
    foo<double> f3= exp3(vx);
    cout <<" f3.eval() = "<< f3.eval() << endl;
    }
    int main( int argc, char** argv, char** envp){
    testfun2();
    return 0;
    }

    //*****************************************************************

    The error it gives (with gcc version 4.4.5) is

    foo4.cpp: In function ‘void testfun2()’:
    foo4.cpp:45: error: no matching function for call to
    ‘exp3(vfoo<double>&)’

    The question is ¿Why doesn't detect de conversion vfoo -> foo?, as you
    see commented,
    I tried to place vfoo after foo and doing the conversion in vfoo
    instead of foo, but
    that didn't work either.

    ¿How could I solve the problem? . My aim is to be able to write
    exp3(vx) without having to do a cast or conversion in testfun2. I know
    that I could write a overloaded function exp3
    whose argument would be a vfoo, that I find that clumsy if I derive a
    lot of classes from basf like vfoo.

    Thanks in advance,

    César.
     
    cesarth, Oct 28, 2011
    #1
    1. Advertising

  2. cesarth

    cesarth Guest

    Hello again, where in the non-template version I write "f3= exp3(f1)"
    I meant "f3= exp3(vx)".
    The problem is still there.

    César
     
    cesarth, Oct 28, 2011
    #2
    1. Advertising

  3. On 10/28/2011 7:24 AM, cesarth wrote:
    > I have a code that works without templating and when I apply templates
    > doesn't.
    > I tried to simplify it as much as possible, but it is a little long.
    >
    > This code works without templating[..]
    >
    > But doesn't with templates:
    >
    > //*****************************************************************
    > #include<iostream>
    > #include<cmath> // exp
    >
    > using namespace std;
    >
    > template<class T> struct basf{
    > virtual T eval(void) const{ cerr<< "ERROR: base class()"<<endl; };
    > };
    > template<class T> ostream& operator<<(ostream&os, const basf<T> & bas)
    > { os<< bas.eval(); return os; };
    >
    > template<class T> struct vfoo: public basf<T>{
    > T * var;
    > vfoo( T * v, const string&rep1 ): var(v), rep(rep1){};
    > void operator=( const T& v ) { *var=v; };
    > // operator foo<T>( ){ foo<T> fun(this); return fun; };
    > // operator foo<T>&( ){ foo<T> fun(this); return fun; };
    > T eval() const{ return *var; };
    > };
    > template<class T> struct foo{
    > basf<T> *fp;
    > foo( basf<T> * pbfun ) : fp(pbfun) { };
    > foo( vfoo<T> &vx ) : fp(&vx) { };
    > // foo( ) { };
    > T eval(void) const{ return fp->eval(); };
    > };
    > template<class T> struct efoo: public basf<T>{
    > foo<T> sub;
    > efoo( foo<T> sf ) : sub(sf) {};
    > operator foo<T>( ){ foo<T> fun(this); return fun; };
    > T eval() const{ return exp( sub.eval() ); };
    > string str(void) const { return "exp("; };
    > };
    >
    > template<class T> efoo<T> exp3( foo<T> sf ) { return
    > efoo<T>( sf ); };
    >
    > void testfun2(void){
    > double x=14.10;
    > vfoo<double> vx(&x,"x");
    > cout<< "vx = "<< vx<< endl;
    > foo<double> f1=vx;
    > cout<<" f1.eval() ="<< f1.eval()<< endl;
    > foo<double> f2= efoo<double>(vx);
    > cout<<" f2.eval() ="<< f2.eval()<< endl;
    > foo<double> f3= exp3(vx);


    So, the template argument for 'exp3' needs to be determined from this
    call, right? 'vx' is a 'vfoo<double>', right? There is no 'exp3'
    function that takes 'vfoo' template instance as its argument. There is,
    however, 'exp3' that takes a 'foo' template instance. That is where it
    breaks down. Trying to find what template argument to instantiate the
    'exp3' with, the compiler cannot come up with any because there is no
    suitable 'exp3'.

    The main difference between that and looking for a suitable function to
    call among some overloaded functions is that the latter *allows
    conversions* for arguments. Matching template arguments to determine
    what template to instantiate or what the template argument is going to
    be, *requires perfect match* from a list of "deducible contexts" and no
    conversions are considered.

    > cout<<" f3.eval() ="<< f3.eval()<< endl;
    > }
    > int main( int argc, char** argv, char** envp){
    > testfun2();
    > return 0;
    > }
    >
    > //*****************************************************************
    >
    > The error it gives (with gcc version 4.4.5) is
    >
    > foo4.cpp: In function ‘void testfun2()’:
    > foo4.cpp:45: error: no matching function for call to
    > ‘exp3(vfoo<double>&)’
    >
    > The question is ¿Why doesn't detect de conversion vfoo -> foo?, as you
    > see commented,


    Because that's prohibited by the Standard for the purposes of template
    argument deduction.

    > I tried to place vfoo after foo and doing the conversion in vfoo
    > instead of foo, but
    > that didn't work either.


    No conversions are considered for the purposes of deducing template
    arguments.

    > ¿How could I solve the problem? . My aim is to be able to write
    > exp3(vx) without having to do a cast or conversion in testfun2. I know
    > that I could write a overloaded function exp3
    > whose argument would be a vfoo, that I find that clumsy if I derive a
    > lot of classes from basf like vfoo.


    I am not sure what you call "the problem". You haven't followed the
    rules of the language. You want to break the rules, and that's an
    unsolvable problem, methinks. It's similar to some folks' statements
    like "I want to overload operator ** to be exponentiation". Well,
    you're not allowed to make up your own syntax, we tell them.

    You can call your 'exp3' with the explicit template argument after it.
    You don't seem to want that. You can overload 'exp3' with 'vfoo'
    template as its argument, but you don't seem to want that either. Well,
    decide what you want, what you can live with, and then use that.

    There is probably a convoluted way to go around the limitation of the
    language that you've hit, but it's all going to be "clumsy", I suppose.

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Oct 28, 2011
    #3
    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. JKop
    Replies:
    3
    Views:
    477
  2. Guest
    Replies:
    0
    Views:
    436
    Guest
    Feb 21, 2007
  3. Lou Pecora
    Replies:
    8
    Views:
    327
  4. recover
    Replies:
    2
    Views:
    809
    recover
    Jul 25, 2006
  5. ejetzer

    Tkinter inheritance mess?

    ejetzer, Apr 5, 2010, in forum: Python
    Replies:
    3
    Views:
    490
    ejetzer
    Apr 8, 2010
Loading...

Share This Page