// Copyright (C) 2011 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_AnY_FUNCTION_Hh_ #define DLIB_AnY_FUNCTION_Hh_ #include "../assert.h" #include "../functional.h" #include "any.h" #include "any_function_abstract.h" namespace dlib { // ---------------------------------------------------------------------------------------- template < class Storage, class F > class any_function_basic; template < class Storage, class R, class... Args > class any_function_basic<Storage, R(Args...)> { private: template<class F> using is_valid = std::enable_if_t<!std::is_same<std::decay_t<F>, any_function_basic>::value && dlib::is_invocable_r<R, F, Args...>::value, bool>; template<typename Func> static auto make_invoker() { return [](void* self, Args... args) -> R { return dlib::invoke(*reinterpret_cast<std::add_pointer_t<Func>>(self), std::forward<Args>(args)...); }; } Storage str; R (*func)(void*, Args...) = nullptr; public: using result_type = R; constexpr any_function_basic(std::nullptr_t) noexcept {} constexpr any_function_basic() = default; constexpr any_function_basic(const any_function_basic& other) = default; constexpr any_function_basic& operator=(const any_function_basic& other) = default; constexpr any_function_basic(any_function_basic&& other) : str{std::move(other.str)}, func{std::exchange(other.func, nullptr)} { } constexpr any_function_basic& operator=(any_function_basic&& other) { if (this != &other) { str = std::move(other.str); func = std::exchange(other.func, nullptr); } return *this; } template<class F, is_valid<F> = true> any_function_basic( F&& f ) : str{std::forward<F>(f)}, func{make_invoker<F&&>()} { } template<class F, is_valid<F> = true> any_function_basic( F* f ) : str{f}, func{make_invoker<F*>()} { } R operator()(Args... args) const { return func(const_cast<void*>(str.get_ptr()), std::forward<Args>(args)...); } void clear() { str.clear(); } void swap (any_function_basic& item) { std::swap(*this, item); } bool is_empty() const noexcept { return str.is_empty() || func == nullptr; } bool is_set() const noexcept { return !is_empty(); } explicit operator bool() const noexcept { return is_set(); } template <typename T> bool contains() const { return str.template contains<T>();} template <typename T> T& cast_to() { return str.template cast_to<T>(); } template <typename T> const T& cast_to() const { return str.template cast_to<T>(); } template <typename T> T& get() { return str.template get<T>(); } }; // ---------------------------------------------------------------------------------------- template <class T, class Storage, class F> T& any_cast(any_function_basic<Storage, F>& a) { return a.template cast_to<T>(); } template <class T, class Storage, class F> const T& any_cast(const any_function_basic<Storage, F>& a) { return a.template cast_to<T>(); } // ---------------------------------------------------------------------------------------- template <class F> using any_function = any_function_basic<te::storage_sbo<16>, F>; template <class F> using any_function_view = any_function_basic<te::storage_view, F>; // ---------------------------------------------------------------------------------------- } #endif // DLIB_AnY_FUNCTION_Hh_