栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

【C++】函数容器实现

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【C++】函数容器实现

#include 
#include 
#include 
#include 
#include 
#include 
#include 

//
// https://github.com/qicosmos/cosmos/blob/master/function_traits.hpp
// https://codechina.gitcode.host/programmer/2016/145-programmer-2016.html
// https://zhuanlan.zhihu.com/p/33330839
//
//

//转换为std::function和函数指针.
template 
struct function_traits;

//普通函数.
template 
struct function_traits
{
public:
    enum
    {
        arity = sizeof...(Args)
    };
    typedef Ret function_type(Args...);
    typedef Ret return_type;
    using stl_function_type = std::function;
    typedef Ret (*pointer)(Args...);

    template 
    struct args
    {
        static_assert(I < arity, "index is out of range, index must less than sizeof Args");
        using type = typename std::tuple_element>::type;
    };

    typedef std::tuple>...> tuple_type;
    typedef std::tuple>...> bare_tuple_type;
};

//函数指针.
template 
struct function_traits : function_traits
{
};

//std::function.
template 
struct function_traits> : function_traits
{
};

//member function.
#define FUNCTION_TRAITS(...)                                                                                      
    template                                           
    struct function_traits : function_traits 
    {                                                                                                             
    };

FUNCTION_TRAITS()
FUNCTION_TRAITS(const)
FUNCTION_TRAITS(volatile)
FUNCTION_TRAITS(const volatile)

//函数对象.
template 
struct function_traits : function_traits
{
};

template 
typename function_traits::stl_function_type to_function(const Function &lambda)
{
    return static_cast::stl_function_type>(lambda);
}

template 
typename function_traits::stl_function_type to_function(Function &&lambda)
{
    return static_cast::stl_function_type>(std::forward(lambda));
}

template 
typename function_traits::pointer to_function_pointer(const Function &lambda)
{
    return static_cast::pointer>(lambda);
}

// ===============================================

template 
struct seq
{
    using type = seq;
};

template 
struct concat;

template 
struct concat, seq> : public seq
{
};

template 
struct make : public concat, typename make::type>
{
};

template <>
struct make<1> : public seq<0>
{
};

template <>
struct make<0> : public seq<>
{
};

// ================================================
class FunctionContainer
{
    std::map> invokers_;

public:
    template 
    class invoker
    {
    public:
        static inline void apply(const func &f, void *args)
        {
            using tuple_type = typename function_traits::tuple_type;
            const tuple_type *tp = static_cast(args);
            forward_call(f, *tp);
        }
    };

    template 
    void register_handler(const std::string &name, const Func &f)
    {
        using std::placeholders::_1;
        invokers_[name] = {std::bind(&invoker::apply, f, _1)};
    }

    template 
    void call(const std::string &name, Args &&...args)
    {
        auto item = invokers_.find(name);
        if (item == invokers_.end())
        {
            return;
        }

        auto args_tuple = std::make_tuple(std::forward(args)...);
        char data[sizeof(std::tuple)];
        std::tuple *tp = new (data) std::tuple;
        *tp = args_tuple;

        item->second(tp);
    }

    template 
    static void forward_call(const F &f, const std::tuple &tp)
    {
        call_helper(f, make{}, tp);
    }

    template 
    static decltype(auto) call_helper(const F &f, const seq &, const std::tuple &tp)
    {
        return f(std::get(tp)...);
    }
};

int main()
{
    FunctionContainer fc;

    auto g = [&](int a, int b)
    {
        std::cout << a << " " << b << std::endl;
    };

    auto countup = [&](int stop)
    {
        int x = 0;
        while (x < stop)
        {
            std::cout << "up: " << x << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(1));
            x++;
        }
    };

    fc.register_handler>("g", g);
    fc.register_handler>("countup", countup);

    fc.call("g", 3, 6);
    fc.call("countup", 5);
}

V2

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

//
// https://github.com/qicosmos/cosmos/blob/master/function_traits.hpp
// https://codechina.gitcode.host/programmer/2016/145-programmer-2016.html
// https://zhuanlan.zhihu.com/p/33330839
//
//

//转换为std::function和函数指针.
template 
struct function_traits;

//普通函数.
template 
struct function_traits
{
public:
    enum
    {
        arity = sizeof...(Args)
    };
    typedef Ret function_type(Args...);
    typedef Ret return_type;
    using stl_function_type = std::function;
    typedef Ret (*pointer)(Args...);

    template 
    struct args
    {
        static_assert(I < arity, "index is out of range, index must less than sizeof Args");
        using type = typename std::tuple_element>::type;
    };

    typedef std::tuple>...> tuple_type;
    typedef std::tuple>...> bare_tuple_type;
};

//函数指针.
template 
struct function_traits : function_traits
{
};

//std::function.
template 
struct function_traits> : function_traits
{
};

//member function.
#define FUNCTION_TRAITS(...)                                                                                      
    template                                           
    struct function_traits : function_traits 
    {                                                                                                             
    };

FUNCTION_TRAITS()
FUNCTION_TRAITS(const)
FUNCTION_TRAITS(volatile)
FUNCTION_TRAITS(const volatile)

//函数对象.
template 
struct function_traits : function_traits
{
};

template 
typename function_traits::stl_function_type to_function(const Function &lambda)
{
    return static_cast::stl_function_type>(lambda);
}

template 
typename function_traits::stl_function_type to_function(Function &&lambda)
{
    return static_cast::stl_function_type>(std::forward(lambda));
}

template 
typename function_traits::pointer to_function_pointer(const Function &lambda)
{
    return static_cast::pointer>(lambda);
}

// ===============================================

template 
struct seq
{
    using type = seq;
};

template 
struct concat;

template 
struct concat, seq> : public seq
{
};

template 
struct make : public concat, typename make::type>
{
};

template <>
struct make<1> : public seq<0>
{
};

template <>
struct make<0> : public seq<>
{
};

// ================================================
class FunctionContainer
{
    using TimePoint = std::chrono::high_resolution_clock::time_point;
    using BindFunc = std::function;
    using SleepingTask = std::tuple;

    class TaskCompare
    {

    public:
        TaskCompare() {}

        bool operator()(const SleepingTask &a, const SleepingTask &b)
        {
            return std::get<0>(a) >= std::get<0>(b);
        }
    };

private:
    std::priority_queue, TaskCompare> sleeping_;
    std::map> invokers_;
    std::deque> readys_;

    template 
    class invoker
    {
    public:
        static inline void apply(const func &f, void *args)
        {
            using tuple_type = typename function_traits::tuple_type;
            const tuple_type *tp = static_cast(args);
            forward_call(f, *tp);
        }
        template 
        static inline void apply2(const func &f, std::tuple args)
        {
            using tuple_type = typename function_traits::tuple_type;
            // const tuple_type *tp = static_cast(args);
            forward_call(f, args);
        }
    };

public:
    template 
    void register_handler(const std::string &name, const Func &f)
    {
        using std::placeholders::_1;
        invokers_[name] = {std::bind(&invoker::apply, f, _1)};
    }

    //

    template 
    void call_soon( const Func &f, Args... args)
    {
        using std::placeholders::_1;

        auto args_tuple = std::make_tuple(std::forward(args)...);
        char data[sizeof(std::tuple)];
        std::tuple *tp = new (data) std::tuple;
        *tp = args_tuple;

        readys_.push_back(std::bind(&invoker::template apply2, f, *tp));
        // ↑↑↑↑↑↑ 这个template的添加太TM坑了!!!↑↑↑↑↑↑
        // https://segmentfault.com/q/1010000021553693
        // https://github.com/eliasdaler/metaStuff/issues/12
    }

    template 
    void call_later(int seconds, const Func &f, Args... args)
    {

        using std::placeholders::_1;
        auto args_tuple = std::make_tuple(std::forward(args)...);

        TimePoint deadline = std::chrono::high_resolution_clock::now() + std::chrono::seconds(seconds);
        sleeping_.push(std::make_tuple(deadline, std::bind(&invoker::template apply2, f, args_tuple)));
    }

    void run()
    {
        while (!readys_.empty() || !sleeping_.empty())
        {
            if (readys_.empty())
            {
                auto top = sleeping_.top();
                sleeping_.pop();
                ;
                if (std::get<0>(top) > std::chrono::high_resolution_clock::now())
                {
                    std::this_thread::sleep_for(std::get<0>(top) - std::chrono::high_resolution_clock::now());
                }
                readys_.push_back(std::get<1>(top));
            }

            auto f = readys_.front();
            readys_.pop_front();
            f();
        }
    }

    //
private:
    template 
    void call(const std::string &name, Args &&...args)
    {
        auto item = invokers_.find(name);
        if (item == invokers_.end())
        {
            return;
        }

        auto args_tuple = std::make_tuple(std::forward(args)...);
        char data[sizeof(std::tuple)];
        std::tuple *tp = new (data) std::tuple;
        *tp = args_tuple;

        item->second(tp);
    }

private:
    template 
    static void forward_call(const F &f, const std::tuple &tp)
    {
        call_helper(f, make{}, tp);
    }

    template 
    static decltype(auto) call_helper(const F &f, const seq &, const std::tuple &tp)
    {
        return f(std::get(tp)...);
    }
};

void sum(int a, int b, int *ret)
{

    *ret = a + b;
}

int main()
{
    FunctionContainer fc;

    auto g = [&](int a, int b)
    {
        std::cout << a << " " << b << std::endl;
    };

    std::function countdown;
    countdown = [&](int s)
    {
        if (s > 0)
        {
            std::cout << "down: " << s << std::endl;
            // std::this_thread::sleep_for(std::chrono::seconds(1));
            // fc.call_soon(countdown, s - 1);
            fc.call_later(4, countdown, s - 1);
        }
    };

    std::function countup;
    countup = [&](int stop, int x_)
    {
        int x = x_;
        if (x < stop)
        {
            std::cout << "up: " << x << std::endl;
            // std::this_thread::sleep_for(std::chrono::seconds(1));
            // fc.call_soon(countup, stop, x + 1);
            fc.call_later(4, countup, stop, x + 1);
        }
    };

    // std::function s = sum;

    // fc.register_handler>("g", g);
    // fc.register_handler>("countup", countup);
    // fc.register_handler>("sum", s);

    // fc.call("g", 3, 6);
    // fc.call("countup", 5);

    // int r;
    // fc.call("sum", 3, 6, &r);
    // std::cout << r << std::endl;

    fc.call_soon>(countdown, 6);
    fc.call_soon>(countup, 6, 0);
    fc.run();
}
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号