如何使用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号