Re: [問題] cpp的function pointer傳遞

作者: loveme00835 (髮箍)   2020-10-01 09:24:17
物件的操作需要以下兩個資訊:
1. 物件的參考/指標 (pointer to object)
2. 該物件的成員參考/指標 (pointer to member)
因為你在 B::B_API() 裡會存取到資料成員所以要把資訊透過額外的參數傳遞
給 pfnTest_t, 這通常得做 type erasing 來降低相依性, 不需要這個資訊的
話改傳 null pointer 就好了. 這種設計在 task-based system 還蠻常見的.
typedef int(*pfnTest_t)(void* context, void* x, unsigned char* y,
unsigned int z);
int test_api(pfnTest_t p_pfnTest, void* context);
context 的內容要和 callback 實作相互搭配, 因為標準還不允許用整數型別
來儲存 pointer to member 的資訊, 在這裡只能先傳物件指標作為引數:
int my_callback(void* context, void* x, unsigned char* y,
unsigned int z) {
return reinterpret_cast<B*>(context)->B_API(x, y, z);
}
B b;
test_api(my_callback, std::addressof(b));
上面的實作應該是最直覺的寫法, 但卻存在不少問題:
1. test_api() 呼叫敘述無法表達會轉呼叫 B::B_API() 這件事
2. my_callback() 和 B 耦合性太高, 修改範圍無法只侷限在一個地方
3. my_callback() 這類的 adapter function 實作數會與類別和成員組合
數呈正比
所以我們需要一種可以將類別以及成員函式資訊內嵌在函式裡方法, 並且自動
產生需要的 adapter function, 在 C++ 裡通常會用模板來實現. 因為類別是
成員函式型別的一部分, 我們只需要儲存後者即可, 前者可以透過 meta-func
tion class_of<pmf> 來取得:
template <auto pmf>
struct class_of;
template <
typename Ret, typename C, typename... Args,
Ret (C::*pmf) (Args...)
>
struct class_of<pmf> {
using type = C;
};
static_assert(std::is_same_v<class_of<&B::B_API>::type, B>);
接著我們就可以用 class_of<pmf> 來實作 adapter function 產生器:
template <auto pmf>
int delegate_to(void* context, void* x, unsigned char* y,
unsigned int z) {
auto* const object = reinterpret_cast<
typename class_of<pmf>::type*>(context);
return (object->*pmf)(x, y, z);
}
test_api(delegate_to<&B::B_API>, std::addressof(b));
完整程式碼: https://wandbox.org/permlink/8vEKgUbQojKeOAwK
透過以上程式碼我們就能將更多心力放在商業邏輯, 而不用煩惱語言限制 :)
作者: Lipraxde (Lipraxde)   2020-10-01 10:24:00
但是,test_api 他不能改吧?把 B_API 改成 static 出錯的地方也怪怪的 @@
作者: sighAll (sigh)   2020-10-21 22:48:00
謝謝!

Links booklink

Contact Us: admin [ a t ] ucptt.com