考虑Win32的Runtime Dynamic Linking机制的以下包装器:
#include <boost/noncopyable.hpp>
#include <windows.h>
#include "Exception.hpp"
namespace WindowsApi
{
class RuntimeDynamicLinker : boost::noncopyable
{
HMODULE hMod_;
public:
RuntimeDynamicLinker(const wchar_t * moduleName)
{
hMod_ = LoadLibraryW(moduleName);
if (hMod_ == 0)
{
Exception::Throw(GetLastError());
}
}
template <typename T>
T GetFunction(const char* functionName)
{
FARPROC result = GetProcAddress(hMod_, functionName);
if (result == 0)
{
Exception::Throw(GetLastError());
}
return reinterpret_cast<T>(result);
}
~RuntimeDynamicLinker()
{
FreeLibrary(hMod_);
}
};
}
示例客户端:
typedef NTSTATUS (NTAPI * NtQueryInformationProcess_t)(
IN HANDLE,
IN PROCESS_INFORMATION_CLASS,
OUT PVOID,
IN ULONG,
OUT PULONG);
RuntimeDynamicLinker ntdll(L"ntdll.dll");
NtQueryInformationProcess_t NtQueryInformationProcess =
ntdll.GetFunction<NtQueryInformationProcess_t>("NtQueryInformationProcess");
基本上,我想添加一条错误消息,如果有人试图使用GetFunction
,其中T
不是函数指针类型(因为reinterpret_cast
我被强迫在这里使用可能会隐藏用户错误。)
通过提升类型特征挖掘,我确实发现现有的is_function
模板。但是,is_function
接受对函数的引用,这在我的情况下是用户错误(仅函数指针)。
如果RuntimeDynamicLinker::GetFunction<T>()
不是函数指针类型,如何修改T
以产生合理可理解的编译器错误消息?
(旁注:我从未做过任何类型的TMP,所以不要害怕对TMP的常规用户进行“基本”处理)
答案 0 :(得分:5)
您可以在is_pointer<T>::value && is_function<remove_pointer<T>::type>::value
/ static_assert
中使用BOOST_STATIC_ASSERT
。
答案 1 :(得分:2)
我认为你可以使用Trait课程。
template <typename T>
class IsFunctionPointer
{
public:
bool isFunctionPointer(){return false;};
}
typedef void (*MyFunctionPointer)();
template <>
class IsFunctionPointer<MyFunctionPointer>
{
public:
bool isFunctionPointer(){return true;};
}
这是Trait class的基本概念。
编辑:我会在一些文章链接中介绍特征。 personnally在抓住它们之前我需要一些时间: - )
答案 2 :(得分:2)
你可以这样使用boost::enable_if
:
template <typename T>
T GetFunction(const char* functionName,
typename boost::enable_if_c<boost::is_pointer<T>::value
&& boost::is_function<typename boost::remove_pointer<T>::type>::value>::type* = 0)
{
....
}
这将只允许作为指针和函数的模板参数。其他任何东西都不会在编译时绑定到该函数。
那样:
GetFunction<int(*)()>("foo"); // compiles properly
GetFunction<int()>("foo"); // fails to compile