Skip to content

Instantly share code, notes, and snippets.

@dyigitpolat
Last active November 25, 2021 14:10
Show Gist options
  • Save dyigitpolat/60219e6f34b270e0aa46f344261940a1 to your computer and use it in GitHub Desktop.
Save dyigitpolat/60219e6f34b270e0aa46f344261940a1 to your computer and use it in GitHub Desktop.
type erasure demo with explicit function parameter and return type support.
////////////////// LIBRARY START
#include <memory>
template <typename Common, typename R = void, typename ...Args>
class I {
public:
template <typename T>
I(const T& x) : mptr{std::make_unique<Model<T>>(x)} {}
I(const I& other) : mptr{other.mptr->clone()} {}
R common(Args&& ...args)
{
return mptr->virtual_impl(std::forward<Args>(args)...);
}
private:
struct Concept {
virtual ~Concept() = default;
virtual R virtual_impl(Args&& ...args) const = 0;
virtual std::unique_ptr<Concept> clone() const = 0;
};
template <typename T>
struct Model final : Concept {
Model(const T& x) : mx{x} {}
std::unique_ptr<Concept> clone() const override
{
return std::make_unique<Model>(*this);
}
R virtual_impl(Args&& ...args) const override
{
return Common::impl(mx, std::forward<Args>(args)...);
}
T mx;
};
std::unique_ptr<Concept> mptr;
};
////////////////// LIBRARY END
////////////////// USER CODE
#include <iostream>
#include <vector>
struct Dog {
void cry()
{
std::cout << "hav hav\n";
}
int walk(int distance)
{
std::cout << "dog walk " << distance << "\n";
return distance * 2;
}
};
struct Bird {
void cry()
{
std::cout << "cik cik \n";
}
int walk(int distance)
{
std::cout << "bird walk " << distance << "\n";
return distance * 2;
}
};
struct Cat {
void cry()
{
std::cout << "miyav \n";
}
int walk(int distance)
{
std::cout << "cat walk " << distance << "\n";
return distance * 2;
}
};
struct Lion {
void roar()
{
std::cout << "roar \n";
}
int walk(int distance)
{
std::cout << "lion walk " << distance << "\n";
return distance * 2;
}
};
struct Cryable
{
template <typename Animal>
static void impl(Animal t)
{
t.cry();
}
template <>
void impl(Lion l)
{
l.roar();
}
};
struct Walkable
{
template <typename Animal>
static int impl(Animal t, int distance)
{
return t.walk(distance);
}
};
int main() {
// cry demo
std::vector<I<Cryable>> vec;
vec.push_back(Dog{});
vec.push_back(Cat{});
vec.push_back(Bird{});
vec.push_back(Lion{});
for( auto a : vec)
{
a.common();
}
// walk demo (with return value and parameters)
std::vector<I<Walkable, int, int>> vec2;
vec2.push_back(Dog{});
vec2.push_back(Cat{});
vec2.push_back(Bird{});
vec2.push_back(Lion{});
int i {};
for( auto a : vec2)
{
int double_dist = a.common(i++);
std::cout << double_dist << "\n";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment