Initial commit
diff --git a/include/pybind/mpl.h b/include/pybind/mpl.h
new file mode 100644
index 0000000..ff9c6eb
--- /dev/null
+++ b/include/pybind/mpl.h
@@ -0,0 +1,190 @@
+/*
+ pybind/mpl.h: Simple library for type manipulation and template metaprogramming
+
+ Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
+
+ All rights reserved. Use of this source code is governed by a
+ BSD-style license that can be found in the LICENSE file.
+*/
+
+#if !defined(__PYBIND_MPL_H)
+#define __PYBIND_MPL_H
+
+#include "common.h"
+#include <tuple>
+
+NAMESPACE_BEGIN(pybind)
+NAMESPACE_BEGIN(mpl)
+
+/// Index sequence for convenient template metaprogramming involving tuples
+template<size_t ...> struct index_sequence { };
+template<size_t N, size_t ...S> struct make_index_sequence : make_index_sequence <N - 1, N - 1, S...> { };
+template<size_t ...S> struct make_index_sequence <0, S...> { typedef index_sequence<S...> type; };
+
+/// Helper template to strip away type modifiers
+template <typename T> struct normalize_type { typedef T type; };
+template <typename T> struct normalize_type<const T> { typedef typename normalize_type<T>::type type; };
+template <typename T> struct normalize_type<T*> { typedef typename normalize_type<T>::type type; };
+template <typename T> struct normalize_type<T&> { typedef typename normalize_type<T>::type type; };
+template <typename T> struct normalize_type<T&&> { typedef typename normalize_type<T>::type type; };
+template <typename T, size_t N> struct normalize_type<const T[N]> { typedef typename normalize_type<T>::type type; };
+template <typename T, size_t N> struct normalize_type<T[N]> { typedef typename normalize_type<T>::type type; };
+
+NAMESPACE_BEGIN(detail)
+
+/// Strip the class from a method type
+template <typename T> struct remove_class {};
+template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...)> { typedef R type(A...); };
+template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...) const> { typedef R type(A...); };
+
+/**
+ * \brief Convert a lambda function to a std::function
+ * From http://stackoverflow.com/questions/11893141/inferring-the-call-signature-of-a-lambda-or-arbitrary-callable-for-make-functio
+ */
+template <typename T> struct lambda_signature_impl {
+ using type = typename remove_class<
+ decltype(&std::remove_reference<T>::type::operator())>::type;
+};
+template <typename R, typename... A> struct lambda_signature_impl<R (A...)> { typedef R type(A...); };
+template <typename R, typename... A> struct lambda_signature_impl<R (&)(A...)> { typedef R type(A...); };
+template <typename R, typename... A> struct lambda_signature_impl<R (*)(A...)> { typedef R type(A...); };
+template <typename T> using lambda_signature = typename lambda_signature_impl<T>::type;
+template <typename F> using make_function_type = std::function<lambda_signature<F>>;
+
+NAMESPACE_END(detail)
+
+template<typename F> detail::make_function_type<F> make_function(F &&f) {
+ return detail::make_function_type<F>(std::forward<F>(f)); }
+
+NAMESPACE_BEGIN(detail)
+
+struct void_type { };
+
+/// Helper functions for calling a function using a tuple argument while dealing with void/non-void return values
+template <typename RetType> struct tuple_dispatch {
+ typedef RetType return_type;
+ template<typename Func, typename Arg, size_t ... S> return_type operator()(const Func &f, Arg && args, index_sequence<S...>) {
+ return f(std::get<S>(std::forward<Arg>(args))...);
+ }
+};
+
+/// Helper functions for calling a function using a tuple argument (special case for void return values)
+template <> struct tuple_dispatch<void> {
+ typedef void_type return_type;
+ template<typename Func, typename Arg, size_t ... S> return_type operator()(const Func &f, Arg &&args, index_sequence<S...>) {
+ f(std::get<S>(std::forward<Arg>(args))...);
+ return return_type();
+ }
+};
+
+NAMESPACE_END(detail)
+
+/// For lambda functions delegate to their 'operator()'
+template <typename T> struct function_traits : public function_traits<typename detail::make_function_type<T>> { };
+
+/// Type traits for function pointers
+template <typename ReturnType, typename... Args>
+struct function_traits<ReturnType(*)(Args...)> {
+ enum {
+ nargs = sizeof...(Args),
+ is_method = 0,
+ is_const = 0
+ };
+ typedef std::function<ReturnType (Args...)> f_type;
+ typedef detail::tuple_dispatch<ReturnType> dispatch_type;
+ typedef typename dispatch_type::return_type return_type;
+ typedef std::tuple<Args...> args_type;
+
+ template <size_t i> struct arg {
+ typedef typename std::tuple_element<i, args_type>::type type;
+ };
+
+ static f_type cast(ReturnType (*func)(Args ...)) { return func; }
+
+ static return_type dispatch(const f_type &f, args_type &&args) {
+ return dispatch_type()(f, std::move(args),
+ typename make_index_sequence<nargs>::type());
+ }
+};
+
+/// Type traits for ordinary methods
+template <typename ClassType, typename ReturnType, typename... Args>
+struct function_traits<ReturnType(ClassType::*)(Args...)> {
+ enum {
+ nargs = sizeof...(Args),
+ is_method = 1,
+ is_const = 0
+ };
+ typedef std::function<ReturnType(ClassType &, Args...)> f_type;
+ typedef detail::tuple_dispatch<ReturnType> dispatch_type;
+ typedef typename dispatch_type::return_type return_type;
+ typedef std::tuple<ClassType&, Args...> args_type;
+
+ template <size_t i> struct arg {
+ typedef typename std::tuple_element<i, args_type>::type type;
+ };
+
+ static f_type cast(ReturnType (ClassType::*func)(Args ...)) { return std::mem_fn(func); }
+
+ static return_type dispatch(const f_type &f, args_type &&args) {
+ return dispatch_type()(f, std::move(args),
+ typename make_index_sequence<nargs+1>::type());
+ }
+};
+
+/// Type traits for const methods
+template <typename ClassType, typename ReturnType, typename... Args>
+struct function_traits<ReturnType(ClassType::*)(Args...) const> {
+ enum {
+ nargs = sizeof...(Args),
+ is_method = 1,
+ is_const = 1
+ };
+ typedef std::function<ReturnType (const ClassType &, Args...)> f_type;
+ typedef detail::tuple_dispatch<ReturnType> dispatch_type;
+ typedef typename dispatch_type::return_type return_type;
+ typedef std::tuple<const ClassType&, Args...> args_type;
+
+ template <size_t i> struct arg {
+ typedef typename std::tuple_element<i, args_type>::type type;
+ };
+
+ static f_type cast(ReturnType (ClassType::*func)(Args ...) const) {
+ return std::mem_fn(func);
+ }
+
+ static return_type dispatch(const f_type &f, args_type &&args) {
+ return dispatch_type()(f, std::move(args),
+ typename make_index_sequence<nargs+1>::type());
+ }
+};
+
+/// Type traits for std::functions
+template <typename ReturnType, typename... Args>
+struct function_traits<std::function<ReturnType(Args...)>> {
+ enum {
+ nargs = sizeof...(Args),
+ is_method = 0,
+ is_const = 0
+ };
+ typedef std::function<ReturnType (Args...)> f_type;
+ typedef detail::tuple_dispatch<ReturnType> dispatch_type;
+ typedef typename dispatch_type::return_type return_type;
+ typedef std::tuple<Args...> args_type;
+
+ template <size_t i> struct arg {
+ typedef typename std::tuple_element<i, args_type>::type type;
+ };
+
+ static f_type cast(const f_type &func) { return func; }
+
+ static return_type dispatch(const f_type &f, args_type &&args) {
+ return dispatch_type()(f, std::move(args),
+ typename make_index_sequence<nargs>::type());
+ }
+};
+
+NAMESPACE_END(mpl)
+NAMESPACE_END(pybind)
+
+#endif /* __PYBIND_MPL_H */