Skip to content

Instantly share code, notes, and snippets.

@Enelar
Created March 20, 2014 10:30
Show Gist options
  • Save Enelar/9660991 to your computer and use it in GitHub Desktop.
Save Enelar/9660991 to your computer and use it in GitHub Desktop.
With this gist you could get array of object overloaded methods(lambda+circuit) by its names. For simple example i support only constructors, but i hope you realize `what you should change` to get every function you want.
#include <functional>
#include <iostream>
using namespace std;
struct objT
{
};
struct a : objT
{
a()
{
cout << "A void" << endl;
}
a(int b)
{
cout << "A " << b << endl;
}
};
struct b : objT
{
b()
{
cout << "B void" << endl;
}
b(int b)
{
cout << "B " << b << endl;
}
};
template<class ConstructingObjectT>
struct constructor
{
template<typename... _Args>
static ConstructingObjectT *construct(_Args &&...arg)
{
return new ConstructingObjectT(forward<_Args>(arg)...);
}
template<typename... _Args>
static function<ConstructingObjectT *(_Args&&...)> GetConstructMethod()
{
auto F = [](_Args&&... arg)
{
return construct(forward<_Args>(arg)...);
};
return F;
}
template<typename Parent, typename... _Args>
static function<Parent *(_Args&&...)> ParentConstruct()
{
return GetConstructMethod<_Args...>();
}
};
#include <tuple>
#include <deque>
template<class Parent, class Tuple, int level = -1>
struct fabric
{
template<typename... _Args>
static Parent *Make(int id, _Args&&...args)
{
if (level != id + 1)
return fabric<Parent, Tuple, level - 1>::Make(id, forward<_Args>(args)...);
return ThisMaker(forward<_Args>(args)...);
}
template<typename... _Args>
static Parent *ThisMaker(_Args &&...args)
{
auto f = FunctorThisMaker<_Args...>();
return f(forward<_Args>(args)...);
}
template<typename... _Args>
static function<Parent *(_Args &&...)> FunctorThisMaker()
{
typedef typename tuple_element<level - 1, Tuple>::type selected_type;
auto ret = constructor<selected_type>::ParentConstruct<Parent, _Args...>();
return ret;
}
template<typename... _Args>
static deque<function<Parent *(_Args &&...)>> GetFunctors()
{
auto ret = fabric<Parent, Tuple, level - 1>::GetFunctors<_Args...>();
ret.push_back(FunctorThisMaker<_Args...>());
return ret;
}
};
template<class Parent, class Tuple>
struct fabric<Parent, Tuple, -1>
{
static const int size = tuple_size<Tuple>::value;
template<typename... _Args>
static Parent *Make(int id, _Args&&...args)
{
return fabric<Parent, Tuple, size>::Make<_Args...>(id, forward<_Args>(args)...);
}
template<typename... _Args>
static deque<function<Parent *(_Args &&...)>> GetFunctors()
{
return fabric<Parent, Tuple, size>::GetFunctors<_Args...>();
}
};
template<class Parent, class Tuple>
struct fabric<Parent, Tuple, 0>
{
template<typename... _Args>
static Parent *Make(int id, _Args&&...args)
{
throw "OUT OF FABRIC RANGE";
}
template<typename... _Args>
static deque<function<Parent *(_Args &&...)>> GetFunctors()
{
return{};
}
};
int main()
{
// пример разрешения конструктора для конкретного типа
auto f1 = constructor<a>::GetConstructMethod<int>();
auto f2 = constructor<a>::GetConstructMethod<>();
f1(6);
f2();
typedef tuple<a, b> types;
typedef fabric<objT, types> example;
// пример рекурсивного разрешения конструктора для типа по номеру
example::Make(0, 5);
example::Make(1, 5);
example::Make(0);
example::Make(1);
// пример динамического(константного) разрешения конструктора
auto void_constructors = example::GetFunctors<>();
void_constructors[0]();
void_constructors[1]();
auto int_constructors = example::GetFunctors<int>();
int_constructors[0](2);
int_constructors[1](3);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment