Last active
November 25, 2021 14:10
-
-
Save dyigitpolat/60219e6f34b270e0aa46f344261940a1 to your computer and use it in GitHub Desktop.
type erasure demo with explicit function parameter and return type support.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
////////////////// 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