HOME

Polymorphism without virtual funcions

type_ptr is a type that can be used to hold objects in a container for instance, and can be used to select function in runtime.

Sample

struct Box
{
  ~Box()
  {
    std::cout << "~box" << std::endl;
  }
};

struct Circle
{
  ~Circle()
  {
    std::cout << "~circle" << std::endl;
  }
};

void Print(Box& box)
{
  std::cout << "box" << std::endl;
}

void Print(Circle& circle)
{
  std::cout << "circle" << std::endl;
}

struct F
{
  template<class T> static void Call(T& r) { Print(r); }
};

void Test1()
{
  std::vector<type_ptr> v;

  v.emplace_back(new Box());
  v.emplace_back(new Circle());

  //Option 1 
  for (auto & item : v)
  {
    if (auto p = item.is_ptr<Box>())
    {
      Print(*p);
    }
    else if (auto p = item.is_ptr<Circle>())
    {
      Print(*p);
    }
  }

  //Option 2 
  for (auto & item : v)
  {
    switch (is_index<Box, Circle>(item))
    {
    case 1:
      Print(item.ref<Box>());
      break;
    case 2:
      Print(item.ref<Circle>());
      break;
    default:
      break;
    }
  }

  //Option 3  
  for (auto & item : v)
  {
    Select<F, Box, Circle>(item);
  }
}

int _tmain(int argc, _TCHAR* argv[])
{
  Test1();
  return 0;
}


type_ptr.h ```cpp

include "stdafx.h"

include

include

include

include

include

class type_ptr { template static void Delete(void* p) { delete (T*)p; }

protected:

void(DeleteF)(void); void * ptr; const type_info* tinfo;

public:

typeptr(typeptr&& other) { ptr = other.ptr; tinfo = other.tinfo; DeleteF = other.DeleteF;

other.ptr = nullptr;
other.tinfo = nullptr;
other.DeleteF = nullptr;

}

template type_ptr(T* p) { ptr = p; tinfo = &typeid(*p); DeleteF = &Delete; }

typeptr() { ptr = nullptr; typeinfo* tinfo = nullptr; }

~type_ptr() { if (DeleteF != nullptr) { DeleteF(ptr); ptr = nullptr; } }

template bool is() const { return (*tinfo == typeid(T)); }

template T* is_ptr() const { if (is()) { return (T*)ptr; } return nullptr; }

template T& ref() { assert(is_ptr() != nullptr); return ((T)ptr); } };

template int isindeximp(const type_ptr&) { return -1; }

template int isindeximp(const type_ptr& tp) { if (tp.is()) { return N; }

return isindeximp(tp); }

template int isindex(const typeptr& tp) { return isindeximp<1, TN...>(tp); }

template void callimp(const typeptr&) { }

template void callimp(const typeptr& tp) { if (auto p = tp.is_ptr()) { return F::Call(*p); }

return call_imp(tp); }

template void Select(const typeptr& tp) { return callimp(tp); }