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場所で誰かが使用しようとした場合にエラーメッセージを追加したいと思います(ここで使用することを余儀なくされると、ユーザーエラーが隠される可能性があるため)。Treinterpret_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>::valueで使用できます。static_assertBOOST_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 に答える