How can I (at compile time) determine if typename is the name of a function pointer?

Consider the following wrapper around the Win32 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 a client example:

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 would like to add an error message if someone is trying to use GetFunctionwhere T- this is something other than the type of the function pointer (because reinterpret_castwhich I have to use here could otherwise hide user errors).

Delving into features like boost, I found that there was an existing template is_function. However, it is_functionaccepts links to functions that would be a user error in my case (only function pointers).

RuntimeDynamicLinker::GetFunction<T>(), , T ?

( : TMP, , "" TMP)

+3
3

is_pointer<T>::value && is_function<remove_pointer<T>::type>::value static_assert/BOOST_STATIC_ASSERT.

+5

, 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.

EDIT: . personnally , : -)

http://accu.org/index.php/journals/442

+2

You can use boost::enable_iflike this:

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 allow only the template parameter, which is a pointer, as well as a function. Everything else will not be bound to the function at compile time.

So, to:

GetFunction<int(*)()>("foo"); // compiles properly
GetFunction<int()>("foo"); // fails to compile
+2
source

Source: https://habr.com/ru/post/1779725/


All Articles