zoukankan      html  css  js  c++  java
  • function_traits2 通过对函数特征的学习深入理解模板

    通过对函数特征的学习深入理解模板

    /*
     * 函数特征
     *  学习及改进自《深入应用C++11 代码优化与工程级应用》
     *
     * 符号概念:
     *  F       - 函数概念(可调用对象)
     *  R       - 返回值类型
     *  K       - 类(class)类型
     *  Args... - 形参类型包
     */
    #ifndef __FUNCTION_TRAITS_H__
    #define __FUNCTION_TRAITS_H__
    
    #include <functional>
    #include <tuple>
    #include <type_traits>
    
    // 主模板
    template <typename F>
    struct function_traits;
    
    // 普通函数特征
    template<typename R, typename... Args>
    struct function_traits<R(Args...)>
    {
        enum { arity = sizeof...(Args) };
        using return_type       = R;
        using function_type     = R(Args...);
        using stl_function_type = std::function<function_type>;
        using pointer           = R(*)(Args...);
    
        template<size_t I>
        using type = typename std::tuple_element<I, std::tuple<Args...>>::type;
    
        template<size_t I>
        struct args
        {
            static_assert(I < arity, "Index must less than sizeof Args.");
            using type = typename std::tuple_element<I, std::tuple<Args...>>::type;
        };
    };
    
    // 函数指针特征
    template<typename R, typename... Args>
    struct function_traits<R(*)(Args...)> : function_traits<R(Args...)> {};
    
    // std::function 特征
    template<typename R, typename... Args>
    struct function_traits<std::function<R(Args...)>> : function_traits<R(Args...)> {};
    
    // 成员函数特征
    #define KLASS_MEMBER_FUNCTION_TRAITS(...)
    template<typename R, typename K, typename... Args>
    struct function_traits<R(K::*)(Args...) __VA_ARGS__ > : function_traits<R(Args...)> {};
    
    KLASS_MEMBER_FUNCTION_TRAITS()
    KLASS_MEMBER_FUNCTION_TRAITS(const)
    KLASS_MEMBER_FUNCTION_TRAITS(volatile)
    KLASS_MEMBER_FUNCTION_TRAITS(const volatile)
    #undef KLASS_MEMBER_FUNCTION_TRAITS
    
    // std::bind 特征匹配
    template <typename R, typename F, typename... Args>
    struct function_traits<std::_Binder<R, F, Args...>> : function_traits<F> {};
    
    // 仿函数特征
    template<typename F>
    struct function_traits : function_traits<decltype(&F::operator())> {};
    
    // stl_function_type 别名
    template <typename F>
    using stl_function_type = typename function_traits<std::remove_reference_t<F>>::stl_function_type;
    
    // 可调用对象(函数,函数指针,静态函数,仿函数,std::bind,std::function)转stl函数
    template <typename F>
    stl_function_type<F> to_function(F const& f)
    {
        return static_cast<stl_function_type<F>>(f);
    }
    
    template <typename F>
    stl_function_type<F> to_function(F && f)
    {
        return static_cast<stl_function_type<F>>(std::forward<F>(f));
    }
    
    #endif
    

    测试代码

    #include <iostream>
    #include "function_traits.hpp"
    using namespace std;
    
    static void test_function_traits();
    
    template <typename T>
    void print() { cout << typeid(T).name() << endl; }
    
    template <typename F>
    void print_function_traits(F && f)
    {
        using ft = function_traits<std::remove_reference_t<F>>;
        cout << "RT     " << typeid(ft::return_type).name() << endl;
        cout << "FT     " << typeid(ft::function_type).name() << endl;
        cout << "SFT    " << typeid(ft::stl_function_type).name() << endl;
        cout << "PT     " << typeid(ft::pointer).name() << endl;
        cout << "AT(0)  " << typeid(ft::type<0>).name() << endl;
        cout << "AT(1)  " << typeid(ft::type<1>).name() << endl;
    }
    
    int main()
    {
        test_function_traits();
        return 0;
    }
    
    // 函数
    void test01(int a, int b){
        cout << __FUNCTION__ << endl;
    }
    
    // 
    struct Test02
    {
        // 静态函数
        static void sf01(int a, int b) {
            cout << __FUNCTION__ << endl;
        }
    
        // 仿函数
        void operator()(int a, int b)
        {
            cout << __FUNCTION__ << endl;
        }
    
        // 成员函数
        void mf01(int a, int b)
        {
            cout << __FUNCTION__ << endl;
        }
    };
    
    static void test_function_traits()
    {
        auto tf1 = to_function(test01);
        tf1(1,1);
        tf1 = to_function(Test02::sf01);
        tf1(1, 1);
        tf1 = to_function(Test02());
        tf1(1, 1);
        Test02 tt;
        tf1 = to_function([&tt](int a, int b) {cout << "----" << __FUNCTION__ << endl; tt.mf01(a, b); });
        tf1(1, 1);
        auto fb = std::bind(&Test02::mf01, tt, std::placeholders::_1, std::placeholders::_2);
        tf1 = to_function(fb);
        stl_function_type<decltype(tf1)> fr = fb;
        cout << "--------------" << endl;
        cout << typeid(fb).name() << endl;
        cout << typeid(fr).name() << endl;
        cout << "--------------" << endl;
        tf1 = to_function(fr);
        tf1(1, 1);
        print_function_traits(tf1);
    }
    
  • 相关阅读:
    Control Group(CGroup)资源限制组
    系统安全之用户认证
    如何在Linux中禁用和挂起休眠
    ubuntu18 virtualbox启动失败Kernel driver not installed (rc=-1908)
    C# Winform 多线程更新界面UI控件,解决界面卡顿问题(转)
    【573】LaTeX相关技巧
    程序计时函数
    王炸!!Spring 终于对 JVM 动手了…
    ThreadLocalRandom 是线程安全的吗?
    Spring Boot 应用可视化监控,一目了然!
  • 原文地址:https://www.cnblogs.com/yaoyu126/p/12491072.html
Copyright © 2011-2022 走看看