如何使用C++编写一个自定义的函数调用模板类
简介
有时候我们拿到了函数的调用地址,但是需要在call之前做一些判断或者预处理,这时我们就需要封装一个自定义的函数call模板。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <windows.h>
#include <functional>
#include <type_traits>
#include "scopeexit.h"
enum class ECallId
{
    Func1,
    Func2,
};
typedef bool(*func1)(int, int);
class CCaller final
{
public:
    CCaller() = default;
    ~CCaller() = default;
    CCaller (const CCaller &) = default;
    CCaller (CCaller &&) = default;
    CCaller &operator=(const CCaller &) = default;
    CCaller &operator=(CCaller &&) = default;
    template<typename F, class... Args>
    auto callById(ECallId id, Args &&...args)
    {
        InterlockedIncrement(&caller_ref_count_);
        ON_SCOPE_EXIT
        {
            InterlockedDecrement(&caller_ref_count_);
        };
        
        const uintptr_t func_ptr = getFuncAddressById(id);
        if (func_ptr)
        {
            F f = (decltype(f))func_ptr;
            auto task = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
            return task();
        }
        return makeFailedResult<F, Args...>();
    }
private:
    // match return type
    template<typename F, class... Args,
             typename = std::enable_if_t<std::is_same_v<std::invoke_result_t<F, Args...>, int>>>
    static int makeFailedResult()
    {
        return std::invoke_result_t<F, Args...>(0);
    }
    // match return type
    template<typename F, class... Args,
             typename = std::enable_if_t<std::is_same_v<std::invoke_result_t<F, Args...>, bool>>>
    static bool makeFailedResult()
    {
        return std::invoke_result_t<F, Args...>(false);
    }
    uintptr_t getFuncAddressById(ECallId id) const;
    volatile uint32_t caller_ref_count_ = 0;
};
int main(void)
{
    CCaller caller;
    caller.callById<func1>(ECallId::Func1, 1, 2);
    return 0;
}
    本文为博主总结文章,欢迎转载,请注明出处。

                
            
        
浙公网安备 33010602011771号