gpt4 book ai didi

c++ - 在另一个模板函数的定义中解压函数参数类型

转载 作者:行者123 更新时间:2023-11-30 05:19:28 26 4
gpt4 key购买 nike

我正在制作一个类模板来编码函数指针。该函数可以有任何结果类型和参数的数量/类型。这是我的:

LPVOID EncodePtr(LPVOID ptr) {
// Encode...
return ptr;
}

LPVOID DecodePtr(LPVOID ptr) {
// Decode...
return ptr;
}

template<class T>
class encoded_ptr {
public:

typedef encoded_ptr<T> _Myt;

encoded_ptr() {
ptr_ = (T*)EncodePtr(nullptr);
}

// Irresponsible?
template<class _OtherType>
encoded_ptr(_OtherType ptr) {
ptr_ = (T*)DecodePtr((LPVOID)ptr);
}

~encoded_ptr() {
ptr_ = (T*)EncodePtr(nullptr);
}

// Makes it possible to call the function directly
template<class... _Args>
typename std::result_of<T*(_Args...)>::type operator()(_Args... _Ax) {
T* fn = get();

return fn(_Ax...);
}

T* get() const {
return (T*)DecodePtr((LPVOID)ptr_);
}

bool is_set() {
return (get() != nullptr);
}

private:
T* ptr_;
};

它按预期工作。例如:

encoded_ptr<decltype(MessageBoxA)> MsgBox;
MsgBox = &MessageBoxA; // Could also initialize in the constructor

// (HWND)0 is justified by the actual problem in the question
MsgBox((HWND)0, "Test message!", "Test", 0);

第一个问题是括号运算符()的方式被声明不允许 Visual Studio 的 IntelliSense 发挥它的魔力并给我有关函数参数的提示:

template<class... _Args>
typename std::result_of<T*(_Args...)>::type operator()(_Args... _Ax) {
T* fn = get();

return fn(_Ax...);
}

而不是使用 (_Args... _Ax) ,我想解包实际的函数参数,以便 IntelliSense 可以正确给出提示。

当前行为是:

Wrong

预期行为是:

enter image description here

第二个问题是,以这种方式调用函数,编译器不进行基本转换,迫使我转换 NULL(void*)NULL , 0(HWND)0等。当使用带有很多参数的函数时,这很烦人。

也许在实现中有一些错误,但我不是模板专家。另外,我不知道问题的标题是否合适。

感谢任何帮助。

编辑:

到目前为止我尝试过的(@OlegBogdanov 的建议):

template<class T, class... Args>
class encoded_ptr;

template<class T, class... Args>
class encoded_ptr<T(Args...)> {
public:

typedef encoded_ptr<T> _Myt;

using Fptr = T(*)(Args...);
encoded_ptr(Fptr ptr) {
ptr_ = (Fptr)EncodePtr((LPVOID)ptr);
}

// Makes it possible to call the function directly
typename T operator()(Args... _Ax) {
Fptr fn = get();

return fn(std::forward<Args>(_Ax)...);
}

Fptr get() const {
return (T*)DecodePtr((LPVOID)ptr_);
}

bool is_set() {
return (get() != nullptr);
}

private:
Fptr ptr_;
};

结果:无法实例化/使用构造函数:Incomplete type is not allowed .

编辑:

这是正确的方向,问题是调用约定。

更改:

class encoded_ptr<T(Args...)>class encoded_ptr<T(__stdcall)(Args...)> , 和

using Fptr = T(*)(Args...)using Fptr = T(__stdcall*)(Args...)

我正在尝试检测调用约定而不是对其进行硬编码。

最佳答案

我觉得你的期望

template<class... _Args>
typename std::result_of<T*(_Args...)>::type operator()(_Args... _Ax) {
T* fn = get();

return fn(_Ax...);
}

错了。它完全忽略了你的目标函数参数列表(你使用了穷人类型的删除)并传递(我想使用单词'forwards'但那是不准确的)无论调用者给出什么。因此 0 in

MsgBox(0, "Test message!", "Test", 0);

被推断为 int 并且您必须将其转换为 HWND,否则编译器将无法猜测。

您真正在做的是重新发明 std::function或者上面的 wrapper 。

如果你真的认为std::function不足以满足您的需求,您将不得不复制其实现的一部分,即您至少需要

    template<class R, class... Args>
class encoded_ptr; // leaving this undefined

template<class R, class... Args>
class encoded_ptr<R(Args...)> {

using Fptr = R(*)(Args...);
encoded_ptr(Fptr ptr) {
ptr_ = (T*)DecodePtr((LPVOID)ptr);
}
...

在你的类型中捕获参数列表

调用运算符会重新使用它而不是随机输入传递的参数:

// this must not be here -> template<class... _Args>
R operator()(Args... _Ax) {
T* fn = get()

return fn(std::forward<Args>(_Ax)...);
}

编辑:

不能再存储T*了,T只是一个返回类型,按Fptr存储

关于c++ - 在另一个模板函数的定义中解压函数参数类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41095146/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com