最近在學習呼叫函式指標的時候想到了一個思路。我使用模板變數引數來構造模板函式,這樣我就可以呼叫函式指標
#include<functional>
#include<Windows.h>
template<class T, class ...Args>
decltype(auto) ExecuteFunc(LPVOID f, Args&& ...args) {
if (f != nullptr) {
return std::function<T>((T*)f)(std::forward<Args>(args)...);
}
}
int main(){
ExecuteFunc<int(HWND, char*, char*, int)>(&MessageBoxA, (HWND)NULL, (char*)"Text", (char*)"caption", MB_OK);
return 0;
}
雖然這段代碼運行的不錯,但是圖片好像有點太長了 有沒有辦法縮短代碼?
我希望代碼可以簡化為呼叫。
ExecuteFunc<int>(&MessageBoxA, (HWND)NULL, (char*)"Text", (char*)"caption", MB_OK);
如果您有一些有趣的想法,請自由表達。
補充說明。一些答案誤解了我的問題并改變了引數的型別,顯然 std::invoke 還沒有這樣做。引數 1 作為函式指標地址傳入,而不是已匯出函式示例 2 的名稱。
LPVOID FunAddr=&MessageBoxA;
int ret=ExecuteFunc<int>(FunAddr, (HWND)NULL, (char*) "Text", (char*) "caption", MB_OK);
int ret=ExecuteFunc< int > 表示函式的回傳值是 int 型別的 FunAddr 是函式的地址,不能直接給出函式的符號名 函式的其余引數
另外我知道 FunAddr 沒有任何可用的型別資訊,但是給定的引數可以提取這個型別資訊并拼接到T(int,int)
template<class T,class . .Args>
T ExecuteFunc(LPVOID f, Args&&... .args) {
}
uj5u.com熱心網友回復:
的實作存在一個問題ExecuteFunc:它不會在每個未定義行為的路徑上回傳一個值。
對我來說,這看起來像是您正在嘗試重新發明std::invoke。std::invoke除了為您執行空檢查之外,還可以做任何事情。
std::invoke(&MessageBoxA, nullptr, "Text", "caption", MB_OK);
如果你真的想自己實作這個,你可以使用這樣的東西:
template<class F, class ...Args>
decltype(auto) ExecuteFunc(F&& f, Args&&...args)
{
if constexpr (std::is_pointer_v<F>)
{
using ResultType = decltype(std::declval<F>()(std::forward<Args>(args)...));
if (f == nullptr)
{
// return the default constructed return value, if a null function pointer is passed
return ResultType{};
}
}
return std::forward<F>(f)(std::forward<Args>(args)...);
}
int AddOne(int i)
{
return i 1;
}
int main()
{
static_assert(std::is_same_v<decltype(ExecuteFunc(&MessageBoxA, nullptr, "Text", "caption", MB_OK)), int>); // just to show the return type is as expected for MessageBoxA
std::cout << ExecuteFunc(&AddOne, 5) << '\n';
std::cout << ExecuteFunc(static_cast<decltype(&AddOne)>(nullptr), 5) << '\n';
std::cout << ExecuteFunc([](int i) {return i 1; }, 5) << '\n';
}
uj5u.com熱心網友回復:
[enter image description here][1]
#include<functional>
#include<Windows.h>
template<class T, class ...Args>
decltype(auto) ExecuteFunc(T f, Args&& ...args) {
f(args...);
}
int main() {
ExecuteFunc(std::function{ MessageBoxA }, (HWND)NULL, (char*)"Text", (char*)"caption", MB_OK);
return 0;
}
uj5u.com熱心網友回復:
感謝所有朋友的支持和評論。您的熱情評論為我提供了建設性的幫助目前我接受了一個更簡單的答案,非常符合我的需求。
代碼和示例如下
template<class T,class F, class ...Args>
inline decltype(auto) ExecuteFunc(F f, Args&&...args) {
return reinterpret_cast<T(*)(Args...)>(f)(args...);
}
例子
#include<Windows.h>
#include<iostream>
template<class T, class F, class ...Args>
inline decltype(auto) ExecuteFunc(F f, Args&&...args) {
return reinterpret_cast<T(*)(Args...)>(f)(args...);
}
int Add(int a, int b) {
return a b;
}
int main(){
//1.
LPVOID funcptr = &Add;
std::cout << ExecuteFunc<int>(funcptr, 1, 2) << std::endl;
//2.
std::cout << ExecuteFunc<int>(Add, 3, 5) << std::endl;
//3.
ExecuteFunc<int>(MessageBoxA,(HWND)NULL, (char*)"Text", (char*)"caption", MB_OK);
return 0;
}
輸出
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/515144.html
標籤:C 模板
上一篇:如何使用多個引數進行模板特化(當其中一個引數的型別已知時)
下一篇:Python,為函式創建一種模板
