私は、関数ポインタをエンコードするクラステンプレートを作成しています。この関数は、結果の型と数/型のパラメータを持つことができます。これは私が持っているものです:別のテンプレート関数の定義における関数のパラメータタイプのアンパック
LPVOID EncodePtr(LPVOID ptr) {
// Encode...
return ptr;
}
LPVOID DecodePtr(LPVOID ptr) {
// Decode...
return ptr;
}
template<class T>
class encoded_ptr {
public:
typedef encoded_ptr<T> _Myt;
encoded_ptr() {
ptr_ = (T*)EncodePtr(nullptr);
}
// Irresponsible?
template<class _OtherType>
encoded_ptr(_OtherType ptr) {
ptr_ = (T*)DecodePtr((LPVOID)ptr);
}
~encoded_ptr() {
ptr_ = (T*)EncodePtr(nullptr);
}
// Makes it possible to call the function directly
template<class... _Args>
typename std::result_of<T*(_Args...)>::type operator()(_Args... _Ax) {
T* fn = get();
return fn(_Ax...);
}
T* get() const {
return (T*)DecodePtr((LPVOID)ptr_);
}
bool is_set() {
return (get() != nullptr);
}
private:
T* ptr_;
};
期待どおりに動作します。例えば:
encoded_ptr<decltype(MessageBoxA)> MsgBox;
MsgBox = &MessageBoxA; // Could also initialize in the constructor
// (HWND)0 is justified by the actual problem in the question
MsgBox((HWND)0, "Test message!", "Test", 0);
最初の問題括弧演算子()
が宣言されている方法は、Visual StudioのIntelliSenseには、その魔法を作り、私は、関数のパラメータについてのヒントを与えることを許可していないということです。
template<class... _Args>
typename std::result_of<T*(_Args...)>::type operator()(_Args... _Ax) {
T* fn = get();
return fn(_Ax...);
}
(_Args... _Ax)
を使用する代わりに、実際の関数パラメータを展開して、IntelliSenseがヒントを正しく与えることができるようにしたいと考えています。
現在の動作は次のとおりです。
期待される動作は次のとおりです。
第二の問題は、このよう関数を呼び出し、コンパイラがないことです基本的なキャストを行い、私にキャストすることを余儀なくされるNULL
〜(void*)NULL
、0
〜(HWND)0
など多くのパラメータを持つ関数を使用する場合、これは面倒です。
多分実装に間違いがありますが、私はテンプレートエキスパートではありません。また、質問のタイトルが適切かどうかはわかりません。
何か助けていただきありがとうございます。
EDIT:私は(OlegBogdanovの提案@)これまでに試した何
:
template<class T, class... Args>
class encoded_ptr;
template<class T, class... Args>
class encoded_ptr<T(Args...)> {
public:
typedef encoded_ptr<T> _Myt;
using Fptr = T(*)(Args...);
encoded_ptr(Fptr ptr) {
ptr_ = (Fptr)EncodePtr((LPVOID)ptr);
}
// Makes it possible to call the function directly
typename T operator()(Args... _Ax) {
Fptr fn = get();
return fn(std::forward<Args>(_Ax)...);
}
Fptr get() const {
return (T*)DecodePtr((LPVOID)ptr_);
}
bool is_set() {
return (get() != nullptr);
}
private:
Fptr ptr_;
};
結果:Incomplete type is not allowed
:コンストラクタを使用/インスタンス化できません。
EDIT:
右方向だった、問題は呼び出し規約ました。
は変更:class encoded_ptr<T(__stdcall)(Args...)>
へ
class encoded_ptr<T(Args...)>
、および
using Fptr = T(*)(Args...)
をusing Fptr = T(__stdcall*)(Args...)
に私の代わりにハードコードされ、それを持つの呼び出し規約を検出しようとしています。
によって店舗、単に戻り値の型では、あなたが効果的にIntelliSenseをしませ戦っているコードの問題? –
私はIntelliSenseと戦っていません。それは逆です。私は提案を受け入れることをうれしく思います。 – karliwson
しかし、コンパイルの問題やランタイムの問題はありませんが、IntelliSenseの説明に満足していないだけですか?これは物語の異なる種類です –