Skip to content

Instantly share code, notes, and snippets.

@quartorz
Last active December 29, 2015 21:49
Show Gist options
  • Save quartorz/7733015 to your computer and use it in GitHub Desktop.
Save quartorz/7733015 to your computer and use it in GitHub Desktop.
caller
#include <iostream>
#include <tuple>
#include <string>
extern void *enabler;
template <class... Functions>
class caller{
template <unsigned... I>
class sequence{
template <unsigned J>
class append_impl{
public:
using type = sequence<I..., J>;
};
template <unsigned...>
class extract{
public:
static const unsigned head = -1;
using tail = void;
};
template <unsigned Head, unsigned... Tail>
class extract<Head, Tail...>{
public:
static const unsigned head = Head;
using tail = sequence<Tail...>;
};
public:
template <unsigned N>
using append = typename append_impl<N>::type;
static const unsigned head = extract<I...>::head;
using tail = typename extract<I...>::tail;
static const unsigned length = sizeof...(I);
};
template <unsigned I>
class make_sequence_impl{
template <unsigned N, bool = N == 0>
class maker{
public:
using type = sequence<>;
};
template <unsigned N>
class maker<N, false>{
public:
using type = typename maker<N - 1>::type::template append<N - 1>;
};
public:
using type = typename maker<I>::type;
};
template <unsigned I>
using make_sequence = typename make_sequence_impl<I>::type;
std::tuple<Functions...> functions;
template <class Sequence, typename std::enable_if<Sequence::length != 0>::type*& = enabler, class... Args>
void call_impl(Args... args)
{
std::get<Sequence::head>(functions)(args...);
call_impl<typename Sequence::tail>(args...);
}
template <class Sequence, typename std::enable_if<Sequence::length == 0>::type*& = enabler, class... Args>
void call_impl(Args...)
{
}
public:
caller(Functions... funcs): functions(funcs...)
{
}
template <class... Args>
void operator()(Args... args)
{
call_impl<make_sequence<sizeof...(Functions)>>(args...);
}
};
template <class... Functions>
caller<Functions...> make_caller(Functions... funcs)
{
return caller<Functions...>(funcs...);
}
void f(const char *s, int a, int b)
{
std::cout << "void f(const char*, int, int): " << s << ' ' << a << ' ' << b << std::endl;
}
class Class1{
public:
void operator()(std::string s, int a, int b)
{
std::cout << "Class1::operator(): " << s << ' ' << a << ' ' << b << std::endl;
}
};
class Class2{
public:
template <class Type>
void operator()(Type s, int a, int b)
{
std::cout << "Class2::operator(): " << s << ' ' << a << ' ' << b << std::endl;
}
};
int main()
{
make_caller()();
auto caller = make_caller([](const char *s, int a, ...){
std::cout << "first lambda function: " << s << ' ' << a << std::endl;
}, [](const char *s, int a, int b){
std::cout << "second lambda function: " << s << ' ' << a << ' ' << b << std::endl;
}, f, Class1(), Class2());
caller("string1", 0, 1);
std::cout << std::endl;
caller("string2", 2, 3);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment