Index: uspace/lib/cpp/Makefile
===================================================================
--- uspace/lib/cpp/Makefile	(revision ddd287dc2aac1957273c2dabebaa4bf45369f764)
+++ uspace/lib/cpp/Makefile	(revision 69cc156f04ce61a5e531de44a1b59899507959ec)
@@ -60,4 +60,5 @@
 	src/__bits/test/bitset.cpp \
 	src/__bits/test/deque.cpp \
+	src/__bits/test/functional.cpp \
 	src/__bits/test/list.cpp \
 	src/__bits/test/map.cpp \
Index: uspace/lib/cpp/include/__bits/functional/bind.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/functional/bind.hpp	(revision ddd287dc2aac1957273c2dabebaa4bf45369f764)
+++ uspace/lib/cpp/include/__bits/functional/bind.hpp	(revision 69cc156f04ce61a5e531de44a1b59899507959ec)
@@ -163,6 +163,6 @@
                 }
 
-            private:
-                function<decay_t<F>> func_;
+            private: // TODO: This has problem with member function pointers.
+                function<remove_reference_t<F>> func_;
                 tuple<decay_t<Args>...> bound_args_;
 
@@ -183,5 +183,5 @@
                     bind_arg_filter<ActualArgs...> filter{forward<ActualArgs>(args)...};
 
-                    return aux::invoke(
+                    return aux::INVOKE(
                         func_,
                         filter[get<Is>(bound_args_)]...
Index: uspace/lib/cpp/include/__bits/functional/invoke.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/functional/invoke.hpp	(revision ddd287dc2aac1957273c2dabebaa4bf45369f764)
+++ uspace/lib/cpp/include/__bits/functional/invoke.hpp	(revision 69cc156f04ce61a5e531de44a1b59899507959ec)
@@ -52,5 +52,5 @@
 
     template<class R, class T, class T1, class... Ts>
-    decltype(auto) invoke(R T::* f, T1&& t1, Ts&&... args)
+    decltype(auto) INVOKE(R T::* f, T1&& t1, Ts&&... args)
     {
         if constexpr (is_member_function_pointer<decltype(f)>::value)
@@ -88,5 +88,5 @@
 
     template<class F, class... Args>
-    decltype(auto) invoke(F&& f, Args&&... args)
+    decltype(auto) INVOKE(F&& f, Args&&... args)
     {
         // (1.5)
Index: uspace/lib/cpp/include/__bits/functional/reference_wrapper.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/functional/reference_wrapper.hpp	(revision ddd287dc2aac1957273c2dabebaa4bf45369f764)
+++ uspace/lib/cpp/include/__bits/functional/reference_wrapper.hpp	(revision 69cc156f04ce61a5e531de44a1b59899507959ec)
@@ -75,7 +75,7 @@
 
             template<class... Args>
-            result_of_t<type&(Args&&...)> operator()(Args&&... args) const
+            decltype(auto) operator()(Args&&... args) const
             {
-                return invoke(*data_, std::forward<Args>(args)...);
+                return aux::INVOKE(*data_, std::forward<Args>(args)...);
             }
 
Index: uspace/lib/cpp/include/__bits/test/tests.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/test/tests.hpp	(revision ddd287dc2aac1957273c2dabebaa4bf45369f764)
+++ uspace/lib/cpp/include/__bits/test/tests.hpp	(revision 69cc156f04ce61a5e531de44a1b59899507959ec)
@@ -274,4 +274,15 @@
             const char* name() override;
     };
+
+    class functional_test: public test_suite
+    {
+        public:
+            bool run(bool) override;
+            const char* name() override;
+        private:
+            void test_reference_wrapper();
+            void test_function();
+            void test_bind();
+    };
 }
 
Index: uspace/lib/cpp/include/__bits/type_traits/result_of.hpp
===================================================================
--- uspace/lib/cpp/include/__bits/type_traits/result_of.hpp	(revision ddd287dc2aac1957273c2dabebaa4bf45369f764)
+++ uspace/lib/cpp/include/__bits/type_traits/result_of.hpp	(revision 69cc156f04ce61a5e531de44a1b59899507959ec)
@@ -62,5 +62,5 @@
             is_class<typename decay<F>::type>::value ||
             is_member_pointer<typename decay<F>::type>::value,
-            decltype(aux::invoke(declval<F>(), declval<ArgTypes>()...))
+            decltype(aux::INVOKE(declval<F>(), declval<ArgTypes>()...))
         >::type
     >
Index: uspace/lib/cpp/include/impl/functional.hpp
===================================================================
--- uspace/lib/cpp/include/impl/functional.hpp	(revision ddd287dc2aac1957273c2dabebaa4bf45369f764)
+++ uspace/lib/cpp/include/impl/functional.hpp	(revision 69cc156f04ce61a5e531de44a1b59899507959ec)
@@ -46,5 +46,5 @@
     decltype(auto) invoke(F&& f, Args&&... args)
     {
-        return aux::invoke(forward<F>(f)(forward<Args>(args)...));
+        return aux::INVOKE(forward<F>(f)(forward<Args>(args)...));
     }
 
@@ -67,5 +67,5 @@
                 decltype(auto) operator()(Args&&... args)
                 {
-                    return invoke(func_, forward<Args>(args)...);
+                    return INVOKE(func_, forward<Args>(args)...);
                 }
 
Index: uspace/lib/cpp/include/impl/mutex.hpp
===================================================================
--- uspace/lib/cpp/include/impl/mutex.hpp	(revision ddd287dc2aac1957273c2dabebaa4bf45369f764)
+++ uspace/lib/cpp/include/impl/mutex.hpp	(revision 69cc156f04ce61a5e531de44a1b59899507959ec)
@@ -791,5 +791,5 @@
             // TODO: exception handling
 
-            aux::invoke(forward<Callable>(func), forward<Args>(args)...);
+            aux::INVOKE(forward<Callable>(func), forward<Args>(args)...);
             flag.called_ = true;
         }
Index: uspace/lib/cpp/src/__bits/test/functional.cpp
===================================================================
--- uspace/lib/cpp/src/__bits/test/functional.cpp	(revision 69cc156f04ce61a5e531de44a1b59899507959ec)
+++ uspace/lib/cpp/src/__bits/test/functional.cpp	(revision 69cc156f04ce61a5e531de44a1b59899507959ec)
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2018 Jaroslav Jindrak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <__bits/test/tests.hpp>
+#include <functional>
+#include <type_traits>
+#include <utility>
+
+using namespace std::placeholders;
+
+namespace std::test
+{
+    namespace aux
+    {
+        int f1(int a, int b)
+        {
+            return a + b;
+        }
+
+        int f2(int a, int b)
+        {
+            return a * 10 + b;
+        }
+
+        void f3(int& a, int& b)
+        {
+            a = 42;
+            b = 1337;
+        }
+
+        struct Foo
+        {
+            int add(int a)
+            {
+                return a + data;
+            }
+
+            int data;
+        };
+    }
+
+    bool functional_test::run(bool report)
+    {
+        report_ = report;
+        start();
+
+        test_reference_wrapper();
+        test_function();
+        test_bind();
+
+        return end();
+    }
+
+    const char* functional_test::name()
+    {
+        return "functional";
+    }
+
+    void functional_test::test_reference_wrapper()
+    {
+        int x{4};
+        auto ref = std::ref(x);
+
+        test("reference_wrapper equivalence after construction (cast)", (ref == x));
+        test("reference_wrapper equivalence after construction (get)", (ref.get() == x));
+
+        ref.get() = 5;
+        test_eq("reference_wrapper equivalence after modification pt1", ref.get(), 5);
+        test_eq("reference_wrapper equivalence after modification pt2", x, 5);
+
+        int y{10};
+        ref = y;
+        test_eq("reference_wrapper equivalence after assignment pt1", ref.get(), 10);
+        test_eq("reference_wrapper equivalence after assignment pt2", x, 5);
+
+        std::function<int(int, int)> wrapped_f1{&aux::f1};
+        auto fref = std::ref(wrapped_f1);
+        auto res = fref(2, 5);
+        test_eq("reference_wrapper function invoke", res, 7);
+    }
+
+    void functional_test::test_function()
+    {
+        std::function<int(int, int)> f1{&aux::f1};
+        auto res1 = f1(1, 2);
+
+        test_eq("function from function pointer", res1, 3);
+
+        int x{};
+        std::function<char(char)> f2{[&](auto c){ x = 42; return ++c; }};
+        auto res2 = f2('B');
+
+        test_eq("function from lambda", res2, 'C');
+        test_eq("function from lambda - capture", x, 42);
+
+        test("function operator bool", (bool)f2);
+        f2 = nullptr;
+        test("function nullptr assignment", !f2);
+    }
+
+    void functional_test::test_bind()
+    {
+        auto f1 = std::bind(aux::f1, _1, 1);
+        auto res1 = f1(3);
+
+        test_eq("bind placeholder", res1, 4);
+
+        auto f2 = std::bind(aux::f2, _2, _1);
+        auto res2 = f2(5, 6);
+
+        test_eq("bind reverse placeholder order", res2, 65);
+
+        int x{};
+        int y{};
+        auto f3 = std::bind(aux::f3, _1, std::ref(y));
+        f3(std::ref(x));
+
+        test_eq("bind std::ref as bound", y, 1337);
+        test_eq("bind std::ref as unbound", x, 42);
+
+        auto f4 = std::bind(aux::f2, x, y);
+        auto res3 = f4();
+
+        test_eq("bind all arguments bound", res3, 1757);
+
+        aux::Foo foo{5};
+        auto f5 = std::mem_fn(&aux::Foo::add);
+        auto res4 = f5(&foo, 4);
+
+        test_eq("mem_fn", res4, 9);
+
+        /* auto f5 = std::bind(&aux::Foo::add, _1, _2); */
+        /* auto res4 = f4(&foo, 10); */
+
+        /* test_eq("bind to member function", res4, 19); */
+    }
+}
