Skip to content

Instantly share code, notes, and snippets.

@vesim987
Last active March 23, 2016 18:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vesim987/a73327f352982244a039 to your computer and use it in GitHub Desktop.
Save vesim987/a73327f352982244a039 to your computer and use it in GitHub Desktop.
easy bind
#include <functional>
#include <utility>
#include "functor_traits.hpp"
namespace vtl {
template<int> struct placeholder{ };
}//vtl
namespace std {
template<int Id>
struct is_placeholder<vtl::placeholder<Id>> : std::integral_constant<int, Id>{ };
}//std
namespace vtl{
namespace detail {
template<std::size_t... I, class Func, class... Args>
auto bind(std::index_sequence<I...>, const Func &f, Args&&... args) {
return std::bind(f, std::forward<Args>(args)..., placeholder<I + 1>{}...);
}
template<class Func, class... Args>
auto bind(placeholder<0>, const Func &f, Args&&... args) {
return std::bind(f, std::forward<Args>(args)...);
}
}//detail
template<class Func, class... Args, std::size_t number_of_func_args = functor_traits<Func>::number_of_args>
auto bind(const Func & f, Args&&... args){
return detail::bind(
std::conditional_t<number_of_func_args == sizeof...(Args), placeholder<0>,
std::make_index_sequence <number_of_func_args - sizeof...(Args)>>{},
f, std::forward<Args>(args)...);
}
}//vtl
#include <utility>
#include <functional>
#include <tuple>
namespace vtl {
enum class functor_type {
normal = 0,
reference = 1,
pointer = 2
};
namespace detail {
template<functor_type Type, class Ret, class... Args>
struct functor_traits {
constexpr static functor_type type = Type;
constexpr static std::size_t number_of_args = sizeof...(Args);
using functor = std::conditional_t<type == functor_type::normal,
Ret(Args...),
std::conditional_t<type == functor_type::reference,
Ret(&)(Args...),
Ret(*)(Args...)>>;
using clean_functor = Ret(Args...);
using return_type = Ret;
using arguments = std::tuple<Args...>;
template<std::size_t N>
using arg_by_id = typename std::tuple_element<N, arguments>::value;
};
}//detail
template<class Func>
struct functor_traits;
template<class Ret, class... Args>
struct functor_traits<Ret(Args...)> :
detail::functor_traits<functor_type::normal, Ret, Args...> {};
template<class Ret, class... Args>
struct functor_traits<Ret(&)(Args...)> :
detail::functor_traits<functor_type::reference, Ret, Args...> {};
template<class Ret, class... Args>
struct functor_traits<Ret(*)(Args...)> :
detail::functor_traits<functor_type::pointer, Ret, Args...> {};
template<class Class, class Ret, class... Args>
struct functor_traits<Ret(Class::*)(Args...)> :
detail::functor_traits<functor_type::pointer, Ret, Class*, Args...> {};
}//vtl
#include <iostream>
#include "bind.hpp"
struct foo {
void bar(int a, int b) { std::cout << a << " " << b << std::endl; };
};
int main() {
foo f;
vtl::bind(&foo::bar)(&f, 10, 20);
vtl::bind(&foo::bar, &f)(10, 20);
vtl::bind(&foo::bar, &f, 10)(20);
vtl::bind(&foo::bar, &f, 10, 20)();
return 0;
}
//$ ./a.exe
//10 20
//10 20
//10 20
//10 20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment