tags:

views:

116

answers:

6

I know that you cannot templatize a virtual function and I do understand the concept behind it. But I still need a way to get past some errors I am getting. I am able to make my stuff work, but it doesn't look right to me.

I have class called System:

#include "Vector.h"
class System
{
    virtual void VectorToLocal(Vector<T>& global_dir,const Vector<T>* global_pos =  0)      const  = 0;  
};

class UnresolvedSystem : public System
{
    virtual void VectorToLocal(Vector<T>& global_dir,const Vector<T>* global_pos = 0) const
    {
      //do something 
    }  
};

In Vector.h:

tenplate<typename T>
class Vector
{
  //some functions
};

Now I want to templatize VectorToLocal in system.h to take just Vector<T>, but I cannot do it, since it is a virtual function. I want a work-around. I know I can have VectorToLocal take Vector<float>, Vector<double>, etc., as arguments, but I do not want to do it.

+1  A: 

Member function templates cannot be virtual. No two ways about it.

But virtual member functions can take fully-defined types that just happen to use templates:

class System
{
public:
    virtual void DoIt(vector<int>* v);
};


int main()
{
    vector<int> v;
    System s;
    s.DoIt(&v);
    return 0;
}

By the way, why are you implementing your own vector class?

John Dibling
I know that's what I am doing right now, I am calling explicitly by specifying as vector<float>, vector<int> etc. I was wondering if there is a work around. I am using my own Vector class because, this is totally different from std::vector, This is a special class which calculates the Dot product, cross Product , Magnitude etc. Thanks for the instant reply.
jan
A: 

I do not know what you want to do with your vector, but sometimes it is possible to make the template-function call a virtual function that implements the actual behavior. In that case you would implement the template-version in you superclass, and make it call a non-template pure virtual there that does whatever you want to do. This usually only works, if you put restriction on the type-parameter:

#include "Vector.h"
class System
{
    virtual void print( const std::string & ) const = 0;
    template<class T>
    void VectorToLocal(Vector<T>& global_dir,const Vector<T>* global_pos =  0) const {
        print( T.GetName() );
    }
};

class UnresolvedSystem : public System
{
    virtual void print( const std::string & Name ) const {
        std::cout << name << std::endl;
    }  
};

In this case, I assumed that T has a member-function GetName.

Space_C0wb0y
what is iys the otherway around, what if I want to call virtual function which has templatized arguments? Is it possible is the question?
jan
I am sorry, as several people already pointed out, there is no way to make template functions virtual. But if you explain better what you try to achieve, we may be able to show you an alternate solution.
Space_C0wb0y
A: 

If you define a C++ template function, a new function implementation is created for each combination of template argument types. So a single function in source, could be one or hunderds functions in machine code. That's what helps to makes them fast.

Now, the compiler determines which versions of your function to generate by how it is called. If int is never a type parameter, the compiler is not supposted to generate an implementation. Now if you make a call virtual, it gets hard to find out how it's used, and it could be that the definition of the function is not in the header file when compiling a function that uses the template function. Without the source code of the function, the compiler can't create the compiled function.

There's a few other impracticalities you face when C++ would allow virtual template functions. Like how virtual functions are typically implemented.

And that's probably the reason why C++ doesn't allow it. You may think you need it, but there's probably another way, which I'm sure people will help you find if you give us a little more detail on the requirements behind this code snippet.

jdv
A: 

You have several options, all depending on what you're trying to do.

If T is somehow inherent to System (e.g., if System has member variables of type T), you can make the entire class templated on it:

template< typename T >
class System
{
    virtual void VectorToLocal(Vector<T>& global_dir,const Vector<T>* global_pos =  0)      const  = 0;  
};

template< typename T >
class UnresolvedSystem : public System<T>
{
    virtual void VectorToLocal(Vector<T>& global_dir,const Vector<T>* global_pos = 0) const
    {
      //do something 
    }  
};

If T's context is local to VectorToLocal only, then a better design decision would be to factor the function outside the class:

template< typename T >
void VectorToLocal( System& s, Vector<T>& global_dir, ... )
{
   // use s's public interface to make changes to the object
}

Can you provide more detail about the purpose of VectorToLocal?

Artem
I cannot templatize the system class as it inherit from Class called Entity and Entity from class called Record. Sorry forgot to mention it my question. So VectorToLocal has some does some math using Vector and finally sets one of the membervariables in the class System . Example System class contains the member variable called RMat4<float> _mat which is actually a 4x4 matrix.
jan
Artem
A: 

If what you want is to provide a single implementation point then can forward the call to a template

struct base {
   virtual void f( int );
   virtual void f( double );
};

struct derived : base {
   virtual void f( int x ) { f_tmpl(x); }
   virtual void f( double x ) { f_tmpl(x); }

   template <typename T>
   void f_tmpl( T x ) { // ... }
};

I bet that with a typelist you could actually generate the virtual functions, but that would probably just complicate the code.

David Rodríguez - dribeas
Actually thats what I have implemented as of now. Its is not complicated but it looks like one.
jan
+1  A: 

Any of the common ways of eliminating virtual functions, like CRTP, will also help.

Ben Voigt
CRTP stands for Curiously Recurring Template Pattern: http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
Artem