﻿ Thiago's website

## Polymorphism without virtual funcions

type

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

```

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <cassert>

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

protected:

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

public:

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

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

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

type_ptr()
{
ptr = nullptr;
type_info* tinfo = nullptr;
}

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

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

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

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

template<int N>
int is_index_imp(const type_ptr&)
{
return -1;
}

template<int N, class T1, typename... TN>
int is_index_imp(const type_ptr& tp)
{
if (tp.is<T1>())
{
return N;
}

return is_index_imp<N + 1, TN...>(tp);
}

template<typename... TN>
int is_index(const type_ptr& tp)
{
return is_index_imp<1, TN...>(tp);
}

template<class F>
void call_imp(const type_ptr&)
{
}

template<class F, class T1, typename... TN>
void call_imp(const type_ptr& tp)
{
if (auto p = tp.is_ptr<T1>())
{
return F::Call(*p);
}

return call_imp<F, TN...>(tp);
}

template<class F, typename... TN>
void Select(const type_ptr& tp)
{
return call_imp<F, TN...>(tp);
}

```