开发者

Template Specialization over derived class

I don't know if it is possible, I checked on StackOverflow, I found a lot of stuff but nothing that really fit my problem (or I don't see the relation). What I'd like to do is something like that:

class Bean
{
    public:
    Bean(){}
virtual ~Bean(){}
    template <class T>
    bool set_(T){return false开发者_C百科;}
    template <class T>
    bool get_(T&){return false;}
};
template <class T>
class GenericBean: public Bean
{
    protected:
    T type;
};
class Prova :  public GenericBean<int>
{
    public:
      Prova(){type = 0;}

   template<int> bool set_(int value){ type=value;}
   template<int> bool get_(int& value){value = type;}

};

I'd like to have on object like Prova, cast to Bean and get the specialized function, What I want to do is something like this:

#include <vector>
#include "Bean.h"

using namespace std;
class VirtualMessage
{
public:
    VirtualMessage(void){}
    virtual ~VirtualMessage(void){} 

    template <class ReturnValue, class Item>
    bool Get(ReturnValue & val)
    {
            for(size_t i = 0; i < m_vData.size(); i++)
            {
                if(m_vData[i].get_<ReturnValue>(val))
                  return true;
            }
    }
    template <class Item, class Value>
    bool Set(Value val)
    {
         Item bean;
         if(bean.set_<Value>(val))
         {
           m_vData.push_back(bean);
           return true;
         }
         return false;
     }
protected:
     vector<Bean> m_vData;
};

Main:

#include "VirtualMessage.h"
#include "Bean.h"
int main()
{
    VirtualMessage msg;
    if(msg.Set<Prova ,int>(4))
        printf("Test 1 passed");
}

this code doesn't compile

Maybe nobody will use it, but I wrote something that fits my need. It's not perfect, I have to work on it but is a begin:

#define UNIQUE(T)   unsigned int GetID(){return UniqueType<T>::id();}

struct UniqueTypeBase 
{ 
   static unsigned int _ids; 
}; 

unsigned int UniqueTypeBase::_ids = 0; 
template <class T> 
struct UniqueType : public UniqueTypeBase 
{ 
   static const unsigned int id() 
   { 
      static unsigned int typeId = 0; 
      if (typeId == 0) 
         typeId = ++_ids; 
      return typeId; 
    } 
 }; 


template <class T>
class TemplateBean
{
  public:
     T m_tValue;
     template<class T> set_(T){return false;}
     template<class T> get_(T&){return false;}

     bool set_(T value){    m_tValue    =   value;      return true;}
     bool get_(T& value)    {   value       =   m_tValue;return true;}
};

class Prova :  public TemplateBean<int>
{
public:
    UNIQUE(Prova)
    Prova(){m_tValue = 0;}
};
class Prova2 :  public TemplateBean<float>
{
   public:
     UNIQUE(Prova2)
     Prova2(){m_tValue = 0;}
};


class VirtualMessage
{
  public:
    VirtualMessage(void){}
    virtual ~VirtualMessage(void){} 
    template <class Item, class ReturnValue>
      bool Get(ReturnValue & val)
    {
         Item a;
         map<unsigned int, void*>::iterator it;
         it = m_TagMap.find(a.GetID());
         if(it != m_TagMap.end())
         {
             Item*  pItem = reinterpret_cast<Item*>(it->second);
             if(pItem->get_(val))
                return true;
          }
          return false;
     }
    template <class Item, class Value>
     bool Set(Value val)
    {
      Item* pBean = new Item();
      if(pBean->set_(val))
      {
           m_TagMap[pBean->GetID()] = (void*)pBean;     
           return true;
      }
      return false;
  }
  protected:
    map<unsigned int, void*> m_TagMap;
 };

Test Main:

 int main()
 {
    VirtualMessage msg;
    if(msg.Set<Prova ,int>(4))
        printf("Test 1 passed\n");
    if(!msg.Set<Prova,float>(4.00))
        printf("Test 2 succed\n");
    if(msg.Set<Prova2,float>(4.00))
        printf("Test 3 succed\n");
    int a=0;
    if(msg.Get<Prova>(a))
         printf("%d = 4...if 4=4 test passed\n",a);
     float b=0;
    if(msg.Get<Prova2>(b))
        printf("%f = 4...if 4=4 test passed\n",b);
    getchar();
  }


I think you misunderstood the use of templates.

Templates are blueprints to build classes or methods, that the compiler use to produce real classes and methods (which is called instantiation).

As such, they are purely a compile-time facility. Therefore, they cannot be virtual, and thus overloading a template method in a derived class does not mean what you expect. It hides the base class method when used from derived (statically) but you still call the base class method if you use a reference or pointer to the base class.

What you are trying to achieve is, unfortunately, impossible with templates: it requires a runtime check.

Furthermore, you are using a std::vector<Bean> which will not work as intended. Polymorphic types shall not be manipulated by values in C++, you need a std::vector< std::unique_ptr<Bean> > or boost::ptr_vector<Bean>...

I would recommend reading a good C++ primer before attempting the kind of task you have set yourself upon. You need a basic introduction to C++ paradigms... and gotchas. And there are a lot of gotchas.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜