Skip to content

Instantly share code, notes, and snippets.

@kikairoya
Created June 11, 2010 05:04
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 kikairoya/434075 to your computer and use it in GitHub Desktop.
Save kikairoya/434075 to your computer and use it in GitHub Desktop.
#include <functional>
#include <tuple>
namespace detail {
template <int N>
struct placeholder { };
}
namespace std {
template <int N>
struct is_placeholder< ::detail::placeholder<N> >: std::integral_constant<int, N> { };
}
namespace detail {
template <size_t N, size_t M>
struct iota {
typedef decltype(
std::tuple_cat(
std::declval<std::tuple<std::integral_constant<int, M> > >(),
std::declval<typename iota<N, M + 1>::type>())) type;
};
template <size_t N>
struct iota<N, N> {
typedef std::tuple<std::integral_constant<int, N> > type;
};
template <class F, class... Idx1, typename T, class... Idx2>
inline auto bind_helper(F f, const std::tuple<Idx1...> *, T &&v, const std::tuple<Idx2...> *)
-> decltype(std::bind(f, placeholder<Idx1::value>()..., std::forward<T>(v), placeholder<Idx2::value>()...))
{
return std::bind(f, placeholder<Idx1::value>()..., std::forward<T>(v), placeholder<Idx2::value>()...);
}
template <bool, size_t Pos, typename T, typename Fn, typename... Args>
struct ptrinit_wrapper_impl {
static T exec(Fn fn, Args &&...args) {
T v;
(bind_helper(
fn,
(typename iota<Pos, 1>::type *)NULL,
&v,
(typename iota<sizeof...(Args), Pos+1>::type *)NULL
)
)(std::forward<Args>(args)...);
return v;
}
};
template <size_t Pos, typename T, typename Fn, typename... Args>
struct ptrinit_wrapper_impl<false, Pos, T, Fn, Args...> {
static T exec(Fn fn, Args &&...args) {
T v;
fn(std::forward<Args>(args)..., &v);
return v;
}
};
template <typename T, typename Fn, typename... Args>
struct ptrinit_wrapper_impl<true, 0, T, Fn, Args...> {
static T exec(Fn fn, Args &&...args) {
T v;
fn(&v, std::forward<Args>(args)...);
return v;
}
};
}
template <size_t Pos, typename T, typename Fn, typename... Args>
inline T ptrinit_wrapper(Fn fn, Args &&...args) {
return detail::ptrinit_wrapper_impl<(sizeof...(Args)>Pos), Pos, T, Fn, Args...>::exec(fn, std::forward<Args>(args)...);
}
#include <iostream>
void fn1(int *p, int a, int b, int c) {
*p = b;
std::cout << a << ',' << b << ',' << c << std::endl;
}
void fn2(int a, int *p, int b, int c) {
*p = b;
std::cout << a << ',' << b << ',' << c << std::endl;
}
void fn4(int a, int b, int c, int *p) {
*p = b;
std::cout << a << ',' << b << ',' << c << std::endl;
}
int main() {
std::cout << ptrinit_wrapper<0, int>(&fn1, 1, 2, 3) << std::endl;
std::cout << ptrinit_wrapper<1, int>(&fn2, 1, 2, 3) << std::endl;
std::cout << ptrinit_wrapper<3, int>(&fn4, 1, 2, 3) << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment