3

考虑以下围绕 Win32 的运行时动态链接机制的包装器:

#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基本上,如果有人尝试使用whereT函数指针类型以外的任何内容,我想添加一条错误消息(因为reinterpret_cast我被迫在此处使用可能会隐藏用户错误)。

挖掘提升类型特征,我确实发现有一个现有的is_function模板。但是,is_function接受对函数的引用,这在我的情况下是用户错误(仅限函数指针)。

如果不是函数指针类型,我如何修改RuntimeDynamicLinker::GetFunction<T>()以产生合理理解的编译器错误消息?T

(旁注:我从来没有做过任何类型的 TMP,所以不要害怕复习那些对 TMP 的普通用户来说“基本”的东西)

4

3 回答 3

5

您可以is_pointer<T>::value && is_function<remove_pointer<T>::type>::valuestatic_assert/中使用BOOST_STATIC_ASSERT

于 2010-12-11T10:05:01.297 回答
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 类的基本思想。

编辑:我将添加一些文章链接来介绍特征。就个人而言,我花了一些时间才掌握它们:-)

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

于 2010-12-11T10:00:50.173 回答
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
于 2010-12-11T10:05:10.360 回答