generate more compact binaries
diff --git a/include/pybind/pybind.h b/include/pybind/pybind.h
index d4ebdc8..e8c4ff5 100644
--- a/include/pybind/pybind.h
+++ b/include/pybind/pybind.h
@@ -22,49 +22,112 @@
 
 NAMESPACE_BEGIN(pybind)
 
+/// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object
 class cpp_function : public function {
-public:
+private:
+    /// Chained list of function entries for overloading
     struct function_entry {
-        std::function<PyObject* (PyObject *)> impl;
+        PyObject * (*impl) (function_entry *, PyObject *, PyObject *);
+        void *data;
         std::string signature, doc;
         bool is_constructor;
+        return_value_policy policy;
         function_entry *next = nullptr;
     };
 
+    /// Picks a suitable return value converter from cast.h
+    template <typename T> using return_value_caster =
+        detail::type_caster<typename std::conditional<
+            std::is_void<T>::value, detail::void_type, typename detail::decay<T>::type>::type>;
+
+    /// Picks a suitable argument value converter from cast.h
+    template <typename ... T> using arg_value_caster =
+        detail::type_caster<typename std::tuple<T...>>;
+public:
     cpp_function() { }
-    template <typename Func> cpp_function(
-        Func &&_func, const char *name = nullptr, const char *doc = nullptr,
-        return_value_policy policy = return_value_policy::automatic,
-        function sibling = function(), bool is_method = false) {
-        /* Function traits extracted from the template type 'Func' */
-        typedef mpl::function_traits<Func> f_traits;
 
-        /* Suitable input and output casters */
-        typedef typename detail::type_caster<typename f_traits::args_type> cast_in;
-        typedef typename detail::type_caster<typename mpl::normalize_type<typename f_traits::return_type>::type> cast_out;
-        typename f_traits::f_type func = f_traits::cast(std::forward<Func>(_func));
+    /// Vanilla function pointers
+    template <typename return_type, typename... arg_type>
+    cpp_function(return_type (*f)(arg_type...), const char *name = nullptr,
+                 const char *doc = nullptr, return_value_policy policy = return_value_policy::automatic,
+                 const function &sibling = function(), bool is_method = false) {
 
-        auto impl = [func, policy](PyObject *pyArgs) -> PyObject *{
+        typedef arg_value_caster<arg_type...> cast_in;
+        typedef return_value_caster<return_type> cast_out;
+
+        auto impl = [](function_entry *entry, PyObject *pyArgs, PyObject *parent) -> PyObject * {
             cast_in args;
-            if (!args.load(pyArgs, true))
-                return nullptr;
-            PyObject *parent = policy != return_value_policy::reference_internal
-                ? nullptr : PyTuple_GetItem(pyArgs, 0);
-            return cast_out::cast(
-                f_traits::dispatch(func, args.operator typename f_traits::args_type()),
-                policy, parent);
+            if (!args.load(pyArgs, true)) return nullptr;
+            auto f = (return_type (*) (arg_type...)) entry->data;
+            return cast_out::cast(args.template call<return_type>(f),
+                                  entry->policy, parent);
         };
 
         initialize(name, doc, cast_in::name() + std::string(" -> ") + cast_out::name(),
-                    sibling, is_method, std::move(impl));
+                    sibling, is_method, policy, impl, (void *) f);
     }
+
+    /// Delegating helper constructor to deal with lambda functions
+    template <typename func>
+    cpp_function(func &&f, const char *name = nullptr,
+                 const char *doc = nullptr,
+                 return_value_policy policy = return_value_policy::automatic,
+                 const function &sibling = function(), bool is_method = false) {
+        initialize(std::forward<func>(f), name, doc, policy, sibling, is_method,
+                   (typename detail::remove_class<decltype(
+                       &std::remove_reference<func>::type::operator())>::type *) nullptr);
+    }
+
+
+    /// Class methods (non-const)
+    template <typename return_type, typename class_type, typename ... arg_type> cpp_function(
+            return_type (class_type::*f)(arg_type...), const char *name = nullptr,
+            const char *doc = nullptr, return_value_policy policy = return_value_policy::automatic,
+            const function &sibling = function(), bool is_method = false) {
+        initialize([f](class_type *c, arg_type... args) -> return_type { return (c->*f)(args...); },
+            name, doc, policy, sibling, is_method, (return_type (*)(class_type *, arg_type ...)) nullptr);
+    }
+
+    /// Class methods (const)
+    template <typename return_type, typename class_type, typename ... arg_type> cpp_function(
+            return_type (class_type::*f)(arg_type...) const, const char *name = nullptr,
+            const char *doc = nullptr, return_value_policy policy = return_value_policy::automatic,
+            const function &sibling = function(), bool is_method = false) {
+        initialize([f](const class_type *c, arg_type... args) -> return_type { return (c->*f)(args...); },
+            name, doc, policy, sibling, is_method, (return_type (*)(const class_type *, arg_type ...)) nullptr);
+    }
+
 private:
+    /// Functors, lambda functions, etc.
+    template <typename func, typename return_type, typename... arg_type>
+    void initialize(func &&f, const char *name, const char *doc,
+                 return_value_policy policy, const function &sibling,
+                 bool is_method, return_type (*)(arg_type...)) {
+
+        typedef arg_value_caster<arg_type...> cast_in;
+        typedef return_value_caster<return_type> cast_out;
+        struct capture { typename std::remove_reference<func>::type f; };
+        void *ptr = new capture { std::forward<func>(f) };
+
+        auto impl = [](function_entry *entry, PyObject *pyArgs, PyObject *parent) -> PyObject *{
+            cast_in args;
+            if (!args.load(pyArgs, true)) return nullptr;
+            func &f = ((capture *) entry->data)->f;
+            return cast_out::cast(args.template call<return_type>(f),
+                                  entry->policy, parent);
+        };
+
+        initialize(name, doc, cast_in::name() + std::string(" -> ") + cast_out::name(),
+                    sibling, is_method, policy, impl, ptr);
+    }
+
     static PyObject *dispatcher(PyObject *self, PyObject *args, PyObject * /* kwargs */) {
         function_entry *overloads = (function_entry *) PyCapsule_GetPointer(self, nullptr);
         PyObject *result = nullptr;
+        PyObject *parent = PyTuple_Size(args) > 0 ? PyTuple_GetItem(args, 0) : nullptr;
         try {
             for (function_entry *it = overloads; it != nullptr; it = it->next) {
-                if ((result = it->impl(args)) != nullptr)
+                if ((result = it->impl(it, args, parent)) != nullptr)
                     break;
             }
         } catch (const error_already_set &) {                                               return nullptr;
@@ -100,15 +163,19 @@
 
     void initialize(const char *name, const char *doc,
                     const std::string &signature, function sibling,
-                    bool is_method, std::function<PyObject *(PyObject *)> &&impl) {
+                    bool is_method, return_value_policy policy,
+                    PyObject *(*impl) (function_entry *, PyObject *, PyObject *),
+                    void *data) {
         if (name == nullptr)
             name = "";
 
         /* Linked list of function call handlers (for overloading) */
         function_entry *entry = new function_entry();
-        entry->impl = std::move(impl);
+        entry->impl = impl;
         entry->is_constructor = !strcmp(name, "__init__");
+        entry->policy = policy;
         entry->signature = signature;
+        entry->data = data;
         if (doc) entry->doc = doc;
 
         if (!sibling.ptr() || !PyCFunction_Check(sibling.ptr())) {
@@ -159,16 +226,15 @@
 class cpp_method : public cpp_function {
 public:
     cpp_method () { }
-    template <typename Func>
-    cpp_method(Func &&_func, const char *name = nullptr, const char *doc = nullptr,
-               return_value_policy policy = return_value_policy::automatic,
-               function sibling = function())
-        : cpp_function(std::forward<Func>(_func), name, doc, policy, sibling, true) { }
+    template <typename func> cpp_method(func &&f, const char *name = nullptr,
+               const char *doc = nullptr, return_value_policy
+               policy = return_value_policy::automatic, function sibling = function())
+        : cpp_function(std::forward<func>(f), name, doc, policy, sibling, true) {}
 };
 
 class module : public object {
 public:
-    PYTHON_OBJECT_DEFAULT(module, object, PyModule_Check)
+    PYBIND_OBJECT_DEFAULT(module, object, PyModule_Check)
 
     module(const char *name, const char *doc = nullptr) {
         PyModuleDef *def = new PyModuleDef();
@@ -214,7 +280,7 @@
 /// Basic support for creating new Python heap types
 class custom_type : public object {
 public:
-    PYTHON_OBJECT_DEFAULT(custom_type, object, PyType_Check)
+    PYBIND_OBJECT_DEFAULT(custom_type, object, PyType_Check)
 
     custom_type(object &scope, const char *name_, const std::string &type_name,
                 size_t type_size, size_t instance_size,
@@ -364,14 +430,13 @@
 
     static void releasebuffer(PyObject *, Py_buffer *view) { delete (buffer_info *) view->internal; }
 };
-
 NAMESPACE_END(detail)
 
 template <typename type, typename holder_type = std::unique_ptr<type>> class class_ : public detail::custom_type {
 public:
     typedef detail::instance<type, holder_type> instance_type;
 
-    PYTHON_OBJECT(class_, detail::custom_type, PyType_Check)
+    PYBIND_OBJECT(class_, detail::custom_type, PyType_Check)
 
     class_(object &scope, const char *name, const char *doc = nullptr)
         : detail::custom_type(scope, name, type_id<type>(), sizeof(type),
@@ -603,6 +668,3 @@
 #if defined(_MSC_VER)
 #pragma warning(pop)
 #endif
-
-#undef PYTHON_OBJECT
-#undef PYTHON_OBJECT_DEFAULT