Topic: Member Template on the type of "this


Author: phalpern@newview.org (Pablo Halpern)
Date: 1999/11/27
Raw View
"Andrei Alexandrescu" <andrewalex@hotmail.com> wrote:

>> Another drawback is the overhead of the virtual base class.
>
>You don't need virtual inheritance for this idiom.

I think you do need virtual inheritence, since an indirect derived class
is not allowed to initialize its non-virtual base classes:

class base : public Cloneable   // Non-virtual inheritence
{
public:
  base() : Cloneable(this) { }
};

class derived : public base
{
public:
  derived() : base() { }  // Oops! Indirectly invokes Cloneable(base*)
  derived() : base(), Cloneable(this) { } // Illegal, Cloneable is not
                                     // a direct base class of derived
};

-------------------------------------------------------------
Pablo Halpern                            phalpern@newview.org

I am self-employed. Therefore, my opinions *do* represent
those of my employer.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/11/12
Raw View
Andrei Alexandrescu wrote:
>
> Valentin Bonnard <Bonnard.V@wanadoo.fr> wrote in message
> news:3816C8ED.A29@wanadoo.fr...
>
> The problem with your solution is this:
>
> >    // I have a macro to get all the forwarding ctors

What about this (untested):

struct Cloneable
{
public:
  template<class T> Cloneable(T*):
    clone_function(clone_helper<T>::do_clone)
  {
  };
  Cloneable* clone() // not virtual
  {
    return clone_function(this);
  }
private:
  Cloneable* (*clone_function)(Cloneable*);
  template<class T>
  struct clone_helper
  {
    static Cloneable* do_clone(Cloneable* p)
    {
      return new T(*(T*)p);
    }
  };
};

class Base: public virtual Cloneable
{
  Base(): Cloneable(this) {}
};

class Derived: public Base
{
  Derived(): Cloneable(this) {}
};

Now instead of overriding clone(), you must pass "this" to the
Cloneable constructor. The advantage is that you can't forget
it, since the virtual inheritance mechanism will not let you
go without constructing the Cloneable virtual base class.
Since the constructor just uses the type to select a function,
the fact that the object isn't yet initialized yet doesn't
matter - the pointer isn't used anyway.

A drawback of this approach is that you cannot use covariant
return types (since there's no overriding of virtual functions).
Another drawback is the overhead of the virtual base class.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 1999/11/13
Raw View
Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote in message
news:382C1086.84C1D99D@physik.tu-muenchen.de...
> What about this (untested):

[use a base class holding a pointer to function]

Yes, this is the solution I found, too. Yet the macro is better because it
doesn't have the overhead of a pointer to function per object.

> A drawback of this approach is that you cannot use covariant
> return types (since there's no overriding of virtual functions).

I don't care. CRT are good-for-nothing anyway.

> Another drawback is the overhead of the virtual base class.

You don't need virtual inheritance for this idiom.


Andrei
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Claude Qu zel" <Claude_Quezel@Syntell.corba>
Date: 1999/10/27
Raw View
You can=92t, but this may help you achieve your goal.

class Base {
public:
    virtual Base* clone() const =3D 0;
};


template<class T>
class BaseImpl : public Base {
public:
    virtual T* clone() const
 {
  return new T(static_cast<T const*>(this));
 }
};

class Derived : public BaseImpl<Derived> {
public:
 Derived() {}
 Derived(Derived const*) {}
    // ...
};




Nicolas Chapados wrote:

> I would like to know if it's possible to define a member template
> whose type matches on the type of "this".  Consider:
>
> class Base {
> public:
>     template<class T>
>     virtual T* clone() const {
>         return new T(this);
>     }
> };
>
> class Derived : public Base {
>     // ...
> };

Claude Qu=E9zel (claude_quezel@syntell.corba)
anti-spam: replace corba by com in private replies
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/10/27
Raw View
Claude Qu=E9zel wrote:

> You can=92t, but this may help you achieve your goal.
>=20
> class Base {
> public:
>     virtual Base* clone() const =3D 0;
> };
>=20
> template<class T>
> class BaseImpl : public Base {
> public:
>     virtual T* clone() const
>  {
>   return new T(static_cast<T const*>(this));
>  }
> };
>=20
> class Derived : public BaseImpl<Derived> {
> public:
>  Derived() {}
>  Derived(Derived const*) {}
>     // ...
> };

Causing MI of base of we derive further and want=20
to apply the same trick. Even if we add a virtual:

template<class T>
class BaseImpl : public virtual Base { ... };

class Der2 : public Der, BaseImpl<Der2> {};

It won't work because there are two overriders=20
for clone (BaseImpl<Der>::clone () and=20
BaseImpl<Der2>::clone ()) and neither one is a=20
final overrider. Here is a possible solution: let's=20
say you wanted this inheritance hierarchy:

   Base
     |
  Derived
     |
  Derived2

Then you write:

struct Base { virtual Base* clone () const =3D 0; }

template <class Me, class BasedOn>
struct Helper : BasedOn
{
    Helper () {}
    template <typename T1>
    Helper (const T1& x1) : BasedOn (x1) {}
    ...
    // I have a macro to get all the forwarding ctors

    Me* clone () const
      { return new (*static_cast<const Me*> (this)); }
};

struct Derived : Helper<Derived, Base> {
   Derived (int);
};

struct Derived2 : Helper<Derived2, Derived> {
   Derived2 ()
     : Helper<Derived2, Derived> (3)  // init Derived base class with 3
    {}
};

and you get:

       Base
        |
  Helper<Derived>
        |
     Derived
        |
  Helper<Derived2>
        |
     Derived2

--=20

Valentin Bonnard
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 1999/10/27
Raw View
Valentin Bonnard <Bonnard.V@wanadoo.fr> wrote in message
news:3816C8ED.A29@wanadoo.fr...

The problem with your solution is this:

>    // I have a macro to get all the forwarding ctors


Andrei
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Claude Qu zel" <Claude_Quezel@Syntell.corba>
Date: 1999/10/28
Raw View
Valentin Bonnard wrote:

> Causing MI of base of we derive further and want
> to apply the same trick. Even if we add a virtual:
>
> template<class T>
> class BaseImpl : public virtual Base { ... };
>
> class Der2 : public Der, BaseImpl<Der2> {};
>
> It won't work because there are two overriders
> for clone (BaseImpl<Der>::clone () and
> BaseImpl<Der2>::clone ()) and neither one is a
> final overrider. Here is a possible solution: let's
> say you wanted this inheritance hierarchy:
>
>    Base
>      |
>   Derived
>      |
>   Derived2
>

How is this ? Note Code not compiled (VC does not support covarainant ret=
urn
types :()

class Base {
public:
    virtual Base* clone() const =3D 0;
    virtual ~Base() {};
};


class Derived : public Base { // interface class
public:
    virtual Derived* clone() const =3D 0;
    virtual void fn11() const =3D 0;
    virtual void fn12() const =3D 0;
};


class Derived2 : public Derived { // interface class
public:
    virtual Derived2* clone() const =3D 0;
    virtual void fn21() const =3D 0;
    virtual void fn22() const =3D 0;
    // ...
};


// implementation helpers general

template <class Implementing, class Base2>
class ImplementingHelper : public Base2 {
public:
 typedef Implementing implementing_class_helper;
};

// implementation helpers specific


template<class Base2>
class BaseImpl : public Base2 {
public:

 virtual implementing_class* clone() const
 {
  return new implementing_class_helper(static_cast<implementing_class_hel=
per
const*>(this));
 }
};


template<class Base2>
class DerivedImpl : public Base2 {
public:
    virtual void fn11() const {}
};


template<class Base2>
class Derived2Impl : public Base2 {
public:
    virtual void fn21() const {}
};


// actual work


class MyImplClass : public
Derived2Impl<DerivedImpl<BaseImpl<ImplementingHelper<MyImplClass, Derived=
2> >
> >
{
public:
    MyImplClass();
    MyImplClass(const MyImplClass*);
    virtual void fn12() const {} // programmer has to work sometimes
    virtual void fn22() const {} // programmer has to work sometimes
};


I get

Base
 |
Derived
 |
Derived2
 |
ImplementingHelper<MyImplClass, Derived2>
 |
BaseImpl<ImplementingHelper<MyImplClass, Derived2> >
 |
DerivedImpl<BaseImpl<ImplementingHelper<MyImplClass, Derived2> > >
 |
Derived2Impl<DerivedImpl<BaseImpl<ImplementingHelper<MyImplClass, Derived=
2> >
> >
 |
MyImplClass

I would like some comments on this way of doing things.

Have a nice day.

Claude Qu=E9zel (claude_quezel@syntell.corba)
anti-spam: replace corba by com in private replies
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: 1999/10/24
Raw View
Nicolas Chapados <chapados@iro.umontreal.ca> writes:

> Can the member template achieve this?

You can't have virtual templates, so the simple answer is: no.

Regards,
Martin
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: jmadsen@rci.rutgers.edu (John Madsen)
Date: 1999/10/24
Raw View
Nicolas Chapados <chapados@iro.umontreal.ca> wrote:

>I would like to know if it's possible to define a member template
>whose type matches on the type of "this".  Consider:
>
>class Base {
>public:
>    template<class T>
>    virtual T* clone() const {
>        return new T(this);
>    }
>};

Section 14.5.2 paragraph 3 of the standard states that a member template
function shall not be virtual.  I'm afraid you'll have to do it by hand :).

John Madsen

jmadsen at rci dot rutgers dot edu
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/10/25
Raw View
John Madsen wrote:

> Nicolas Chapados <chapados@iro.umontreal.ca> wrote:
>
> >I would like to know if it's possible to define a member template
> >whose type matches on the type of "this".  Consider:
> >
> >class Base {
> >public:
> >    template<class T>
> >    virtual T* clone() const {
> >        return new T(this);
> >    }
> >};
>
> Section 14.5.2 paragraph 3 of the standard states that a member template
> function shall not be virtual.  I'm afraid you'll have to do it by hand :).

???

--

Valentin Bonnard
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/10/25
Raw View
No, in C++ there is no way to automatically
generate (instantiate) functions when classes
that derive from a given class are defined.

--

Valentin Bonnard
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Nicolas Chapados <chapados@iro.umontreal.ca>
Date: 1999/10/22
Raw View
I would like to know if it's possible to define a member template
whose type matches on the type of "this".  Consider:

class Base {
public:
    template<class T>
    virtual T* clone() const {
        return new T(this);
    }
};

class Derived : public Base {
    // ...
};

Now, I would like to have the member function clone defined
automatically for Derived.  In other words, I would like the
following two behaviour to have a meaning:

    Derived* X =3D new Derived;
    Derived* cloneX =3D X->clone();

and:

    Base* Y =3D new Derived;
    Base* cloneY =3D Y->clone();

Can the member template achieve this?

    Thank you very much!
    + Nicolas

---
Nicolas Chapados                http://www.iro.umontreal.ca/~chapados
Universit=E9 de Montr=E9al / Labo. d'informatique des syst=E8mes adaptati=
fs
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]