Index: uspace/lib/cpp/include/impl/functional.hpp
===================================================================
--- uspace/lib/cpp/include/impl/functional.hpp	(revision daef596e7da9c68c8b9a6b33dd996a2452436ef4)
+++ uspace/lib/cpp/include/impl/functional.hpp	(revision 614b07ea3b4859be7f21dc877da8f09217527b55)
@@ -30,7 +30,7 @@
 #define LIBCPP_FUNCTIONAL
 
+#include <internal/functional/invoke.hpp>
 #include <limits>
 #include <memory>
-#include <typeinfo>
 #include <type_traits>
 #include <utility>
@@ -38,52 +38,4 @@
 namespace std
 {
-    namespace aux
-    {
-        /**
-         * 20.9.2, requirements:
-         */
-        template<class R, class T, class T1, class... Ts>
-        decltype(auto) invoke(R T::* f, T1&& t1, Ts&&... args)
-        {
-            if constexpr (is_member_function_pointer_v<decltype(f)>)
-            {
-                if constexpr (is_base_of_v<T, remove_reference_t<T1>>)
-                    // (1.1)
-                    return (t1.*f)(forward<Ts>(args)...);
-                else
-                    // (1.2)
-                    return ((*t1).*f)(forward<Ts>(args)...);
-            }
-            else if constexpr (is_member_object_pointer_v<decltype(f)> && sizeof...(args) == 0)
-            {
-                /**
-                 * Note: Standard requires to N be equal to 1, but we take t1 directly
-                 *       so we need sizeof...(args) to be 0.
-                 */
-                if constexpr (is_base_of_v<T, remove_reference_t<T1>>)
-                    // (1.3)
-                    return t1.*f;
-                else
-                    // (1.4)
-                    return (*t1).*f;
-            }
-
-            /**
-             * Note: If this condition holds this will not be reachable,
-             *       but a new addition to the standard (17.7 point (8.1))
-             *       prohibits us from simply using false as the condition here,
-             *       so we use this because we know it is false here.
-             */
-            static_assert(is_member_function_pointer_v<decltype(f)>, "invalid invoke");
-        }
-
-        template<class F, class... Args>
-        decltype(auto) invoke(F&& f, Args&&... args)
-        {
-            // (1.5)
-            return f(forward<Args>(args)...);
-        }
-    }
-
     /**
      * 20.9.3, invoke:
@@ -91,85 +43,7 @@
 
     template<class F, class... Args>
-    result_of_t<F&&(Args&&...)> invoke(F&& f, Args&&... args)
+    decltype(auto) invoke(F&& f, Args&&... args)
     {
         return aux::invoke(forward<F>(f)(forward<Args>(args)...));
-    }
-
-    /**
-     * 20.9.4, reference_wrapper:
-     */
-
-    template<class T>
-    class reference_wrapper
-    {
-        public:
-            using type = T;
-            // TODO: conditional typedefs
-
-            reference_wrapper(type& val) noexcept
-                : data_{&val}
-            { /* DUMMY BODY */ }
-
-            reference_wrapper(type&&) = delete;
-
-            reference_wrapper(const reference_wrapper& other) noexcept
-                : data_{other.data_}
-            { /* DUMMY BODY */ }
-
-            reference_wrapper& operator=(const reference_wrapper& other) noexcept
-            {
-                data_ = other.data_;
-
-                return *this;
-            }
-
-            operator type&() const noexcept
-            {
-                return *data_;
-            }
-
-            type& get() const noexcept
-            {
-                return *data_;
-            }
-
-            template<class... Args>
-            result_of_t<type&(Args&&...)> operator()(Args&&... args) const
-            {
-                return invoke(*data_, std::forward<Args>(args)...);
-            }
-
-        private:
-            type* data_;
-    };
-
-    template<class T>
-    reference_wrapper<T> ref(T& t) noexcept
-    {
-        return reference_wrapper<T>{t};
-    }
-
-    template<class T>
-    reference_wrapper<const T> cref(const T& t) noexcept
-    {
-        return reference_wrapper<const T>{t};
-    }
-
-    template<class T>
-    void ref(const T&&) = delete;
-
-    template<class T>
-    void cref(const T&&) = delete;
-
-    template<class T>
-    reference_wrapper<T> ref(reference_wrapper<T> t) noexcept
-    {
-        return ref(t.get());
-    }
-
-    template<class T>
-    reference_wrapper<const T> cref(reference_wrapper<T> t) noexcept
-    {
-        return cref(t.get());
     }
 
@@ -756,539 +630,4 @@
     template<class Predicate>
     constexpr binary_negate<Predicate> not2(const Predicate& pred);
-
-    /**
-     * 20.9.12, polymorphic function adaptors:
-     */
-
-    namespace aux
-    {
-        // TODO: fix this
-        /* template<class, class T, class... Args> */
-        /* struct is_callable_impl: false_type */
-        /* { /1* DUMMY BODY *1/ }; */
-
-        /* template<class, class R, class... Args> */
-        /* struct is_callable_impl< */
-        /*     void_t<decltype(aux::invoke(declval<R(Args...)>(), declval<Args>()..., R))>, */
-        /*     R, Args... */
-        /* > : true_type */
-        /* { /1* DUMMY BODY *1/ }; */
-
-        /* template<class T> */
-        /* struct is_callable: is_callable_impl<void_t<>, T> */
-        /* { /1* DUMMY BODY *1/ }; */
-
-        template<class Callable, class R, class... Args>
-        R invoke_callable(Callable* clbl, Args&&... args)
-        {
-            return (*clbl)(forward<Args>(args)...);
-        }
-
-        template<class Callable>
-        void copy_callable(Callable* to, Callable* from)
-        {
-            new(to) Callable{*from};
-        }
-
-        template<class Callable>
-        void destroy_callable(Callable* clbl)
-        {
-            if (clbl)
-                clbl->~Callable();
-        }
-    }
-
-    // TODO: implement
-    class bad_function_call;
-
-    template<class>
-    class function; // undefined
-
-    /**
-     * Note: Ideally, this implementation wouldn't
-     *       copy the target if it was a pointer to
-     *       a function, but for the simplicity of the
-     *       implementation, we do copy even in that
-     *       case for now. It would be a nice optimization
-     *       if this was changed in the future.
-     */
-    template<class R, class... Args>
-    class function<R(Args...)>
-    {
-        public:
-            using result_type = R;
-            // TODO: conditional typedefs
-
-            /**
-             * 20.9.12.2.1, construct/copy/destroy:
-             */
-
-            function() noexcept
-                : callable_{}, callable_size_{}, call_{},
-                  copy_{}, dest_{}
-            { /* DUMMY BODY */ }
-
-            function(nullptr_t) noexcept
-                : function{}
-            { /* DUMMY BODY */ }
-
-            function(const function& other)
-                : callable_{}, callable_size_{other.callable_size_},
-                  call_{other.call_}, copy_{other.copy_}, dest_{other.dest_}
-            {
-                callable_ = new uint8_t[callable_size_];
-                (*copy_)(callable_, other.callable_);
-            }
-
-            function(function&& other)
-                : callable_{other.callable_}, callable_size_{other.callable_size_},
-                  call_{other.call_}, copy_{other.copy_}, dest_{other.dest_}
-            {
-                other.callable_ = nullptr;
-                other.callable_size_ = size_t{};
-                other.call_ = nullptr;
-                other.copy_ = nullptr;
-                other.dest_ = nullptr;
-            }
-
-            // TODO: shall not participate in overloading unless aux::is_callable<F>
-            template<class F>
-            function(F f)
-                : callable_{}, callable_size_{sizeof(F)},
-                  call_{(call_t)aux::invoke_callable<F, R, Args...>},
-                  copy_{(copy_t)aux::copy_callable<F>},
-                  dest_{(dest_t)aux::destroy_callable<F>}
-            {
-                callable_ = new uint8_t[callable_size_];
-                (*copy_)(callable_, (uint8_t*)&f);
-            }
-
-            /**
-             * Note: For the moment we're ignoring the allocator
-             *       for simplicity of the implementation.
-             */
-
-            template<class A>
-            function(allocator_arg_t, const A& a) noexcept
-                : function{}
-            { /* DUMMY BODY */ }
-
-            template<class A>
-            function(allocator_arg_t, const A& a, nullptr_t) noexcept
-                : function{}
-            { /* DUMMY BODY */ }
-
-            template<class A>
-            function(allocator_arg_t, const A& a, const function& other)
-                : function{other}
-            { /* DUMMY BODY */ }
-
-            template<class A>
-            function(allocator_arg_t, const A& a, function&& other)
-                : function{move(other)}
-            { /* DUMMY BODY */ }
-
-            // TODO: shall not participate in overloading unless aux::is_callable<F>
-            template<class F, class A>
-            function(allocator_arg_t, const A& a, F f)
-                : function{f}
-            { /* DUMMY BODY */ }
-
-            function& operator=(const function& rhs)
-            {
-                function{rhs}.swap(*this);
-
-                return *this;
-            }
-
-            /**
-             * Note: We have to copy call_, copy_
-             *       and dest_ because they can be templated
-             *       by a type F we don't know.
-             */
-            function& operator=(function&& rhs)
-            {
-                clear_();
-
-                callable_ = rhs.callable_;
-                callable_size_ = rhs.callable_size_;
-                call_ = rhs.call_;
-                copy_ = rhs.copy_;
-                dest_ = rhs.dest_;
-
-                rhs.callable_ = nullptr;
-                rhs.callable_size_ = size_t{};
-                rhs.call_ = nullptr;
-                rhs.copy_ = nullptr;
-                rhs.dest_ = nullptr;
-
-                return *this;
-            }
-
-            function& operator=(nullptr_t) noexcept
-            {
-                clear_();
-
-                return *this;
-            }
-
-            // TODO: shall not participate in overloading unless aux::is_callable<F>
-            template<class F>
-            function& operator=(F&& f)
-            {
-                callable_size_ = sizeof(F);
-                callable_ = new uint8_t[callable_size_];
-                call_ = aux::invoke_callable<F, R, Args...>;
-                copy_ = aux::copy_callable<F>;
-                dest_ = aux::destroy_callable<F>;
-
-                (*copy_)(callable_, (uint8_t*)&f);
-            }
-
-            template<class F>
-            function& operator=(reference_wrapper<F> ref) noexcept
-            {
-                return (*this) = ref.get();
-            }
-
-            ~function()
-            {
-                if (callable_)
-                {
-                    (*dest_)(callable_);
-                    delete[] callable_;
-                }
-            }
-
-            /**
-             * 20.9.12.2.2, function modifiers:
-             */
-
-            void swap(function& other) noexcept
-            {
-                std::swap(callable_, other.callable_);
-                std::swap(callable_size_, other.callable_size_);
-                std::swap(call_, other.call_);
-                std::swap(copy_, other.copy_);
-                std::swap(dest_, other.dest_);
-            }
-
-            template<class F, class A>
-            void assign(F&& f, const A& a)
-            {
-                function{allocator_arg, a, forward<F>(f)}.swap(*this);
-            }
-
-            /**
-             * 20.9.12.2.3, function capacity:
-             */
-
-            explicit operator bool() const noexcept
-            {
-                return callable_ != nullptr;
-            }
-
-            /**
-             * 20.9.12.2.4, function invocation:
-             */
-
-            result_type operator()(Args... args) const
-            {
-                // TODO: throw bad_function_call if !callable_ || !call_
-                if constexpr (is_same_v<R, void>)
-                    (*call_)(callable_, forward<Args>(args)...);
-                else
-                    return (*call_)(callable_, forward<Args>(args)...);
-            }
-
-            /**
-             * 20.9.12.2.5, function target access:
-             */
-
-            const type_info& target_type() const noexcept
-            {
-                return typeid(*callable_);
-            }
-
-            template<class T>
-            T* target() noexcept
-            {
-                if (target_type() == typeid(T))
-                    return (T*)callable_;
-                else
-                    return nullptr;
-            }
-
-            template<class T>
-            const T* target() const noexcept
-            {
-                if (target_type() == typeid(T))
-                    return (T*)callable_;
-                else
-                    return nullptr;
-            }
-
-        private:
-            using call_t = R(*)(uint8_t*, Args&&...);
-            using copy_t = void (*)(uint8_t*, uint8_t*);
-            using dest_t = void (*)(uint8_t*);
-
-            uint8_t* callable_;
-            size_t callable_size_;
-            call_t call_;
-            copy_t copy_;
-            dest_t dest_;
-
-            void clear_()
-            {
-                if (callable_)
-                {
-                    (*dest_)(callable_);
-                    delete[] callable_;
-                    callable_ = nullptr;
-                }
-            }
-    };
-
-    /**
-     * 20.9.12.2.6, null pointer comparisons:
-     */
-
-    template<class R, class... Args>
-    bool operator==(const function<R(Args...)>& f, nullptr_t) noexcept
-    {
-        return !f;
-    }
-
-    template<class R, class... Args>
-    bool operator==(nullptr_t, const function<R(Args...)>& f) noexcept
-    {
-        return !f;
-    }
-
-    template<class R, class... Args>
-    bool operator!=(const function<R(Args...)>& f, nullptr_t) noexcept
-    {
-        return (bool)f;
-    }
-
-    template<class R, class... Args>
-    bool operator!=(nullptr_t, const function<R(Args...)>& f) noexcept
-    {
-        return (bool)f;
-    }
-
-    /**
-     * 20.9.12.2.7, specialized algorithms:
-     */
-
-    template<class R, class... Args>
-    void swap(function<R(Args...)>& f1, function<R(Args...)>& f2)
-    {
-        f1.swap(f2);
-    }
-
-    template<class R, class... Args, class Alloc>
-    struct uses_allocator<function<R(Args...)>, Alloc>
-        : true_type
-    { /* DUMMY BODY */ };
-
-    /**
-     * 20.9.10, bind:
-     */
-
-    namespace aux
-    {
-        template<int N>
-        struct placeholder_t
-        {
-            constexpr placeholder_t() = default;
-            constexpr placeholder_t(const placeholder_t&) = default;
-            constexpr placeholder_t(placeholder_t&&) = default;
-        };
-    }
-
-    template<class T>
-    struct is_placeholder: integral_constant<int, 0>
-    { /* DUMMY BODY */ };
-
-    template<int N> // Note: const because they are all constexpr.
-    struct is_placeholder<const aux::placeholder_t<N>>
-        : integral_constant<int, N>
-    { /* DUMMY BODY */ };
-
-    template<class T>
-    inline constexpr int is_placeholder_v = is_placeholder<T>::value;
-
-    namespace aux
-    {
-        /**
-         * Note: Our internal bind return type has an extra type
-         *       template parameter and an extra bool template parameter.
-         *       We use this for the special version of bind that has
-         *       the return type to have a result_type typedef
-         *       (i.e. when the bool is true, the extra type parameter
-         *       is typedefed as result_type - see the structure below).
-         *       This is just a simplification of the implementation
-         *       so that we don't need to have two return types for
-         *       the two bind functions, because unlike function or
-         *       mem_fn, we know exactly when to make the typedef.
-         */
-
-        template<class, bool = false>
-        struct bind_conditional_result_type
-        { /* DUMMY BODY */ };
-
-        template<class R>
-        struct bind_conditional_result_type<R, true>
-        {
-            using result_type = R;
-        };
-
-        template<class, bool, class, class...>
-        class bind_t;
-
-        /**
-         * Filter class that uses its overloaded operator[]
-         * to filter our placeholders, reference_wrappers and bind
-         * subexpressions and replace them with the correct
-         * arguments (extracts references, calls the subexpressions etc).
-         */
-        template<class... Args>
-        class bind_arg_filter
-        {
-            public:
-                bind_arg_filter(Args&&... args)
-                    : args_{forward<Args>(args)...}
-                { /* DUMMY BODY */ }
-
-                template<class T>
-                constexpr decltype(auto) operator[](T&& t)
-                {
-                    return forward<T>(t);
-                }
-
-                template<int N>
-                constexpr decltype(auto) operator[](const placeholder_t<N>)
-                { // Since placeholders are constexpr, this is the best match for them.
-                    /**
-                     * Come on, it's int! Why not use -1 as not placeholder
-                     * and start them at 0? -.-
-                     */
-                    return get<N - 1>(args_);
-                }
-
-                template<class T>
-                constexpr T& operator[](reference_wrapper<T> ref)
-                {
-                    return ref.get();
-                }
-
-                template<class R, bool B, class F, class... BindArgs>
-                constexpr decltype(auto) operator[](const bind_t<R, B, F, BindArgs...> b)
-                {
-                    return b; // TODO: bind subexpressions
-                }
-
-
-            private:
-                tuple<Args...> args_;
-        };
-
-        template<class R, bool HasResultType, class F, class... Args>
-        class bind_t: public bind_conditional_result_type<R, HasResultType>
-        {
-            public:
-                template<class G, class... BoundArgs>
-                constexpr bind_t(G&& g, BoundArgs&&... args)
-                    : func_{forward<F>(g)},
-                      bound_args_{forward<Args>(args)...}
-                { /* DUMMY BODY */ }
-
-                constexpr bind_t(const bind_t& other) = default;
-                constexpr bind_t(bind_t&& other) = default;
-
-                template<class... ActualArgs>
-                constexpr decltype(auto) operator()(ActualArgs&&... args)
-                {
-                    return invoke_(
-                        make_index_sequence<sizeof...(Args)>{},
-                        forward<ActualArgs>(args)...
-                    );
-                }
-
-            private:
-                function<decay_t<F>> func_;
-                tuple<decay_t<Args>...> bound_args_;
-
-                template<size_t... Is, class... ActualArgs>
-                constexpr decltype(auto) invoke_(
-                    index_sequence<Is...>, ActualArgs&&... args
-                )
-                {
-                    /**
-                     * The expression filter[bound_args_[bind_arg_index<Is>()]]...
-                     * here expands bind_arg_index to 0, 1, ... sizeof...(ActualArgs) - 1
-                     * and then passes this variadic list of indices to the bound_args_
-                     * tuple which extracts the bound args from it.
-                     * Our filter will then have its operator[] called on each of them
-                     * and filter out the placeholders, reference_wrappers etc and changes
-                     * them to the actual arguments.
-                     */
-                    bind_arg_filter<ActualArgs...> filter{forward<ActualArgs>(args)...};
-
-                    return invoke(
-                        func_,
-                        filter[get<Is>(bound_args_)]...
-                    );
-                }
-        };
-    }
-
-    template<class T>
-    struct is_bind_expression: false_type
-    { /* DUMMY BODY */ };
-
-    template<class R, bool B, class F, class... Args>
-    struct is_bind_expression<aux::bind_t<R, B, F, Args...>>
-        : true_type
-    { /* DUMMY BODY */ };
-
-    template<class F, class... Args>
-    aux::bind_t<void, false, F, Args...> bind(F&& f, Args&&... args)
-    {
-        return aux::bind_t<void, false, F, Args...>{forward<F>(f), forward<Args>(args)...};
-    }
-
-    template<class R, class F, class... Args>
-    aux::bind_t<R, true, F, Args...> bind(F&& f, Args&&... args)
-    {
-        return aux::bind_t<R, true, F, Args...>{forward<F>(f), forward<Args>(args)...};
-    }
-
-    namespace placeholders
-    {
-        /**
-         * Note: The number of placeholders is
-         *       implementation defined, we've chosen
-         *       8 because it is a nice number
-         *       and should be enough for any function
-         *       call.
-         * Note: According to the C++14 standard, these
-         *       are all extern non-const. We decided to use
-         *       the C++17 form of them being inline constexpr
-         *       because it is more convenient, makes sense
-         *       and would eventually need to be upgraded
-         *       anyway.
-         */
-        inline constexpr aux::placeholder_t<1> _1;
-        inline constexpr aux::placeholder_t<2> _2;
-        inline constexpr aux::placeholder_t<3> _3;
-        inline constexpr aux::placeholder_t<4> _4;
-        inline constexpr aux::placeholder_t<5> _5;
-        inline constexpr aux::placeholder_t<6> _6;
-        inline constexpr aux::placeholder_t<7> _7;
-        inline constexpr aux::placeholder_t<8> _8;
-    }
 
     /**
