Boost logo

Ublas :

From: Vardan Akopian (vakopian_at_[hidden])
Date: 2005-10-07 14:37:03


Well, fact is, if you don't want your class itself to be a template,
then virtual functions have to be explicitely declared for each type
you want to use them with: there is no getting around this with the
current c++.
Now, the way I suggested has the following advantages:
1) code reuse: in each class in the hierarchy the real body of the
method is implemented only once (exactly as it would have been if
virtual templates were allowed).
2) The forwarding code is trivial, in fact the body of each virtual
function is exactly the same. With your exmaple for each type you will
need to figure out how to get a vector_range out of it, and sometimes
(often) that may be impossible, altough the type may still have vector
semantics, and could be used in the template. I.e. today you have a
vector_range as a common denominator for the types, but that can
quickly change, and you may not even have one at all.
3) The forwarding could have 0 cost (e.g. if the template version can
be inlined), while the version you have has the cost of first
caclulating the subranges, then copying the subranges, then making
another virtual call to the inner function.

I beleive this is the colsest you can get to "virtual templates"
without the BN trick, but I could be wrong, so please let us know what
you find.

Regards.
-Vardan

On 10/7/05, Thomas Lemaire <thomas.lemaire_at_[hidden]> wrote:
> Hi,
>
> I do not really understand how this can solve my problem, I could multiply the
> virtual methods for each input datatype, but this would be a pain to
> implement in derivate classes ! (and there is no need for a template method
> here...)
>
> thomas
>
> On Friday 07 October 2005 14:16, Vardan Akopian wrote:
> > Hi Thomas,
> >
> > If you know exactly which types you will be using, then you can simply
> > forward the virtual functions to a template version:
> >
> > class Foo {
> > virtual void doSomeThing(vector<double> const& v1, vector<double> & v2)
> > {
> > doSomeThing_tmpl(v1, v2);
> > }
> >
> > virtual void doSomeThing(vector_range<vector<double> > const& v1,
> > vector_range<vector<double> > & v2)
> > {
> > doSomeThing_tmpl(v1, v2);
> > }
> >
> > private:
> > template<class Vec1, class Vec2>
> > void doSomeThing_tmpl(Vec1 const& v1, Vec2 & v2);
> > };
> >
> > This is not very elegant, but at least you don't need to do
> > subrange's, and it's trivial to add more types when needed.
> >
> > Hope this helps.
> >
> > -Vardan
> >
> > On 10/7/05, Thomas Lemaire <thomas.lemaire_at_[hidden]> wrote:
> > > On Friday 07 October 2005 01:02, Paul C. Leopardi wrote:
> > > > Could you please elaborate? If your method is virtual, why can it not
> > > > be template? In what way is it different from the virtual template
> > > > member functions which are used in the template class
> > > > glucat::clifford_algebra in GluCat, for example? See
> > > > http://sourceforge.net/projects/glucat/ These functions are inherited
> > > > at compile time by the template classes glucat::matrix_multi and
> > > > glucat::framed_multi, using a variant of the Barton-Nackman trick,
> > > > otherwise known as Curiously Recurring Templates.
> > >
> > > My method cannot be template because the compiler complains about it. It
> > > is a matter of virtual table which would be undefined (I am not 100% sure
> > > of what I am saying...). In your case, the whole class is template.
> > >
> > > > This part of the Wiki talks about runtime polymorphism. The template
> > > > class glucat::clifford_algebra uses compile time polymorphism. Do you
> > > > need runtime polymorphism or could you do what you want using only
> > > > compile time polymorphism?
> > >
> > > Yes, I need need runtime polymorphism, that's the point...
> > >
> > > I would like to achieve something like this:
> > >
> > > class Foo {
> > > /* ... */
> > >
> > > template<class Vec1, class Vec2>
> > > virtual void doSomeThing(Vec1 const& v1, Vec2 & v2);
> > >
> > > // and also with virtual pure method
> > >
> > > /* ... */
> > > };
> > >
> > > Actually I am only using vector<double> and vector_range< vector<double>
> > > >, so I could manage things using intermediate functions and
> > > project/subrange like this:
> > >
> > > class Foo {
> > > /* ... */
> > >
> > > void doSomeThing(vec const& v1, vec & v2) {
> > > doSomething(subrange(v1,0,v1.size()), subrange(v2,0,v2.size()));
> > > };
> > >
> > > void doSomeThing(vec_range const& v1, vec & v2) {
> > > doSomething(v1, subrange(v2,0,v2.size()));
> > > };
> > >
> > > void doSomeThing(vec const& v1, vec_range & v2) {
> > > doSomething(subrange(v1,0,v1.size()), v2);
> > > };
> > >
> > > virtual void doSomeThing(vec_range const& v1, vec_range & v2);
> > >
> > > /* ... */
> > > };
> > >
> > > Sometimes I have 3 vector-arguments for doSomeThing(), it is really a
> > > pain,,, And I also sometime use fixed size vector !!
> > >
> > > cheers,
> > > --
> > > thomas
> > > _______________________________________________
> > > ublas mailing list
> > > ublas_at_[hidden]
> > > http://lists.boost.org/mailman/listinfo.cgi/ublas
> >
> > _______________________________________________
> > ublas mailing list
> > ublas_at_[hidden]
> > http://lists.boost.org/mailman/listinfo.cgi/ublas
>
> --
> thomas
>