作为模板参数的函数指针:是否可以扣除调用约定cdecl / stdcall?

问题描述

我有这样的课程

/**
  Some third party libraries with C interfaces have their own set of functions to allocate and free 
  heap memory buffers aligned to the specification of the library. This class helps to manage such
  buffers in a convenient RAII style

  @tparam Type The type of data to hold in the buffer
  @tparam SizeType The type used for sizes (in most cases either int or size_t)
  @tparam allocFunction A function to call that takes the number of bytes to allocate as argument and returns a pointer
                        of Type* to the allocated memory
  @tparam freeFunction A function to call that takes a void* pointer and frees the previously allocated memory
 */
template <typename Type,typename SizeType,Type* (*allocFunction)(SizeType),void (*freeFunction)(void*)>
class GenericScopedBuffer

这很好用,直到我现在尝试更新仍然是32 Windows版本的较旧产品之一。我们使用一些库,这些库的分配/取消分配函数定义为__stdcall类型,并将它们传递给此类模板,例如

GenericScopedBuffer<char,int,stdcallAllocFunction,stdcallFreeFunction>

导致编译器错误,例如C2440: 'specialization': cannot convert from 'void (__stdcall *)(void *)' to 'void (__cdecl *)(void *)'

一个明显的原因是x86编译器将这样声明的函数指针假定为指向__cdecl函数的指针。现在,由于此类模板实际上应该与函数指针一起使用任何类型的函数,所以我想知道是否有一种方法可以从传入的函数中扣除调用约定类型。但是,__stdcall或__cdecl不是真正的类型,而更像是提示编译器,对吧?

那么以跨平台和通用的方式实现这一目标的好方法是什么?

解决方法

就MSVC而言,

plus()onClick是两种不同的类型。这些限定词是一种用于指定语言链接的标准方法。回想一下,void (__stdcall *)(void *)函数不同于void (__cdecl *)(void *)函数的extern "C"函数,尽管有些编译器使您无需混淆它们。

有两种解决方法。

您可以专用于extern "C++"函数的模板。

您可以告诉编译器您不在乎类型是什么:

extern "FORTRAN"

如果您无权使用现代版本的C ++,则可以按函数类型进行参数设置:

__cdecl

,但是当然您必须手动指定类型。为此,您可以使用template <auto allocFunction,auto freeFunction> class GenericScopedBuffer ,也可以将其与傻傻的宏结合使用,例如

template <typename AllocFuncT,AllocFuncT allocFunction,typename FreeFuncT,FreeFuncT freeFunction> class GenericScopedBuffer

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...