开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜