私はここ数日間、C++で関数ポインタ用の汎用ラッパーを作成しようとしていましたが、私はほぼすべての単一の問題バーを解決することができました。私の主な目標は、関数ポインタを内部に格納した関数として単にオブジェクトを呼び出すことでした。ポインタがどこかを指していたなら、それは通常通り呼び出すが、ヌルポインタは関数を呼び出さないだけで何も起こらないかのように続行する。私はこれを主にコールバック関数の目的に使用するつもりです。関数が呼び出されたかどうかは気にせず、アクションを実行するだけです。それは次のようにほぼ完璧に動作します:Cの '...'パラメータパックをC++のテンプレート値として使用していますか?
template<typename T>
class Action;
template<typename TReturn, typename ... TArgs>
class Action<TReturn(TArgs...)> {
public:
//! Define a type for the Action object
typedef TReturn(*signature)(TArgs...);
//! Constructors
inline Action(const signature& pFunc = nullptr) : mPointer(pFunc) {}
inline Action(const Action& pCopy) : mPointer(pCopy.mPointer) {}
//! Operator Call
inline bool operator() (TReturn& pReturn, TArgs ... pArgs) const { if (!mPointer) return false; pReturn = mPointer(pArgs...); return true; }
//! Operators
inline Action& operator=(const Action& pCopy) { mPointer = pCopy.mPointer; return *this; }
inline Action& operator=(const signature& pFunc) { mPointer = pFunc; return *this; }
inline operator bool() const { return (mPointer != nullptr); }
private:
//! Store a pointer to the callback function
signature mPointer;
};
template<typename ... TArgs>
class Action<void(TArgs...)> {
public:
//! Define a type for the Action object
typedef void(*signature)(TArgs...);
//! Constructors
inline Action(const signature& pFunc = nullptr) : mPointer(pFunc) {}
inline Action(const Action& pCopy) : mPointer(pCopy.mPointer) {}
//! Operator Call
inline bool operator() (TArgs ... pArgs) const { if (!mPointer) return false; mPointer(pArgs...); return true; }
//! Operators
inline Action& operator=(const Action& pCopy) { mPointer = pCopy.mPointer; return *this; }
inline Action& operator=(const signature& pFunc) { mPointer = pFunc; return *this; }
inline operator bool() const { return (mPointer != nullptr); }
private:
//! Store a pointer to the callback function
signature mPointer;
};
しかし、私が最も可能性が高い。このラッパーはデバッグ情報やフォーマットされたテキストの出力で使用するような状況のように感じます。これは、ユーザー定義の関数やprintfなどの組み込み関数を介して行うことができます。 printf関数の署名と一致するアクションは次のように作成されます:
Action<int(const char*, ...)> callback = printf;
、他のどのアクションが振る舞うだろうと同じように動作することができるだろう。私が見つけている問題は、 '...'は、テンプレートの署名を特殊化のいずれかに揃えず、その代わりに最初のプロトタイプだけにすることです。
これはなぜ動作しないのか、そしてコンパイラが必要なクラスの生成を処理できない理由を完全に理解できますが、私は誰かがこれを達成するための卑劣なやり方を知っていることを期待していました。あなたの質問の言及下のコメントとして
#include <utility>
#include <cstdio>
#include <cmath>
template<typename Fn>
class Action {
Fn* function_ptr;
public:
Action() noexcept : function_ptr(nullptr) {}
Action(std::nullptr_t) noexcept : function_ptr(nullptr) {}
Action(const Action& other) : function_ptr(other.function_ptr) {}
Action(Fn f) : function_ptr(f) {}
Action& operator=(const Action& other) {
return (function_ptr = other.function_ptr, *this);
}
Action& operator=(std::nullptr_t) {
return (function_ptr = nullptr, *this);
}
Action& operator=(Fn f) {
return (function_ptr = f, *this);
}
template<typename... Params>
auto operator()(Params&&... params) {
return function_ptr(std::forward<Params>(params)...);
}
};
:すべてのヘルプは非常に感謝:)
'std :: function'を使わないのはなぜですか? – StoryTeller
「アクション」の目的は何ですか? ['std :: function'](http://en.cppreference.com/w/cpp/utility/functional/function)を使用できないという要件はありますか?どのような問題を 'アクション'は 'std :: function'が解決しないのですか? –
https://stackoverflow.com/questions/18370396/why-cant-stdfunction-bind-to-c-style-variadic-functionsは、これを達成する方法についていくつかの解説をしました。私は各バリデーショナルな関数について、あなたを助ける具体的なクラスが必要であると思いますし、あなたが呼び出すことができる関数のv *バリエーションがあることを願っています。 – mksteve