Giriş
C++'ta Template ve virtual metodlar yanyana pek gelemiyorlar. Template parametreleri metodun imzası oldukları anda kalıtımda imza bozuluyor. Java gibi dillerde ise bu problem olmuyor. Java'da şöyle bir sınıfımız olsun.
Çeşitli çözümler var. Benim anladığım en kolay çözüm virtual metodu template'tan kurtarmak. Bir çeşit dispatch'in kullanmak
Template Visitor
Template visitor da dispatch yöntemini kullanıyor. Ben de bir projede şuna benzer bir kod kullandım.
Template Store
T tipi nesneyi saklamak için kullanılır. Önce bir ata sınıf tanımlanır.Şöyle yaparız.
Şöyle yaparız. Parameter nesnesi Interface arayüzünü gerçekleştiren generic bir Interfacer nesnesi içerir. Böylece tanımlı bir sınıfa bir çeşit ata sınıf verme imkanı oluyor.
C++'ta Template ve virtual metodlar yanyana pek gelemiyorlar. Template parametreleri metodun imzası oldukları anda kalıtımda imza bozuluyor. Java gibi dillerde ise bu problem olmuyor. Java'da şöyle bir sınıfımız olsun.
abstract class A<T> {
  abstract void setList(List<? extends T> list);
}class B extends A<Foo> {
  @Override void setList(List<? extends Foo> list) { ...}
}template<size_t SIZE> 
class Data {...};class Generator {
  virtual template<size_t SIZE> Data<SIZE> generate() = 0;
};
class PseudoRandomX : public Generator {
  template<size_t SIZE> Data<SIZE> generate() override {...}
};Çeşitli çözümler var. Benim anladığım en kolay çözüm virtual metodu template'tan kurtarmak. Bir çeşit dispatch'in kullanmak
class Generator {
public:
  template< size_t SIZE >
  Data<SIZE> generate() {
    Data<SIZE> x;
    vgenerate(SIZE, x.pointer_to_internals());
    return x;
  }
protected:
  virtual void vgenerate(size_t size, InternalDataPointer *p) = 0;
};
class PseudoRandomX : public Generator {
  void vgenerate(size_t size, InternalDataPointer *p) override {...}
};Template Visitor
Template visitor da dispatch yöntemini kullanıyor. Ben de bir projede şuna benzer bir kod kullandım.
class DefaultVisitor {
public:
  template <typename T>
  void setMsg (const T& value) {
    visit (value);
  }
   
protected:
  virtual void visitImpl (const std::string & value) {...};   
  virtual void visitImpl (const int & value) {...};Template Store
T tipi nesneyi saklamak için kullanılır. Önce bir ata sınıf tanımlanır.Şöyle yaparız.
class ParameterBase
{
public:
  virtual ~ParameterBase() {}
  template<class T> const T& get() const; //to be implimented 
  template<class T, class U> void setValue(const U& rhs); //to be implimented
};template <typename T>
class Parameter : public ParameterBase
{
public:
  Parameter(const T& rhs) :value(rhs) {}
  const T& get() const {return value;}
  void setValue(const T& rhs) {value=rhs;}    
private:
  T value;
};//Here's the trick: dynamic_cast rather than virtual
template<class T> const T& ParameterBase::get() const
{ 
  return dynamic_cast<const Parameter<T>&>(*this).get(); 
}
template<class T, class U> void ParameterBase::setValue(const U& rhs)
{ 
  return dynamic_cast<Parameter<T>&>(*this).setValue(rhs); 
}std::vector<ParameterBase*> vector;Şöyle yaparız. Parameter nesnesi Interface arayüzünü gerçekleştiren generic bir Interfacer nesnesi içerir. Böylece tanımlı bir sınıfa bir çeşit ata sınıf verme imkanı oluyor.
class Parameter
{
  struct Interface
  {
    virtual void bar() = 0;
    virtual ~Interface(){}
  };
  template <class T>
  struct Interfacer : Interface
  {
    T t;
    Interfacer(T t):t(t){}
    void bar() { t.bar(); }
  };
  std::unique_ptr<Interface> interface;
  public:
    template <class T>
    Parameter(const T & t): interface(new Interfacer<T>(t)){}
    void bar() { interface->bar(); }
};
 
Hiç yorum yok:
Yorum Gönder