How can I (at compile time) determine if a typename is a function pointer typename?
Consider the following wrapper around Win32's Runtime Dynamic Linking mechanism:
#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_);
}
};
}
And an example client:
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");
Basically, I'd like to add an error message if anyone tries to use GetFunction
where T
is anything other than a function pointer type (because the reinterpret_cast
I'm forced to use here could otherwise hide user errors).
Digging through boost type traits, I did find that there's an existing is_function
template. However, is_function
accepts references to functions, which would be a user error in my case (function pointers only).
How can I modify RuntimeDynamicLinker::GetFunction<T>()
to produce a reasonably understandable compiler error message if T
is not a function pointer type?
(Side note: I've never done any kind of TMP, so d开发者_如何学运维on't be afraid to go over things that are "basic" to regular users of TMP)
You could use is_pointer<T>::value && is_function<remove_pointer<T>::type>::value
in a static_assert
/BOOST_STATIC_ASSERT
.
I think you could use a Trait class.
template <typename T>
class IsFunctionPointer
{
public:
bool isFunctionPointer(){return false;};
}
typedef void (*MyFunctionPointer)();
template <>
class IsFunctionPointer<MyFunctionPointer>
{
public:
bool isFunctionPointer(){return true;};
}
this is the basic idea of a Trait class.
EDIT: i will ad a few articles link for introducing traits. personnally It took some time for me before grasping them :-)
http://accu.org/index.php/journals/442
You can use boost::enable_if
like so:
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)
{
....
}
This will only allow a template parameter that is a pointer and also a function. Anything else will not bind to the function at compile time.
So that:
GetFunction<int(*)()>("foo"); // compiles properly
GetFunction<int()>("foo"); // fails to compile
精彩评论