2016-07-02 8 views
1

NULL値を持つことができるいくつかの関数ポインタをラップする必要があります。私は関数ポインタがNULLかどうかをチェックし、ポインタがNULLでない場合は元の関数を呼び出し、ポインタがNULLの場合はデフォルト値を返す汎用クラステンプレートを作成しようとしています。このような何か:NULLチェックを含む汎用C++関数ポインタラッパーを作成できますか?

見ることができるように
//Function typedefs 
typedef void(*foo)(); 
typedef int(*bar)(int u, char *); 

//Function pointers 
foo gfFoo; 
bar gfBar; 

//Wrapper class 
template<typename T, typename... Args> 
class WrapFuncObj { 
    T* f; 
public: 
    WrapFuncObj(T* t) { 
     f = t; 
    } 
    typename std::result_of<T(Args...)>::type operator()(Args&&... args) { 
     if(f != nullptr){ 
      return (*f)(std::forward<Args>(args)...); 
     } 
     else 
     { 
      return 0; //RETURN something for non-void types 
     } 
    } 
}; 

template<typename T, typename... Args> 
class WrapFuncObjVoid { 
    T* f; 
public: 
    WrapFuncObjVoid(T* t) { 
     f = t; 
    } 
    typename std::result_of<T(Args...)>::type operator()(Args&&... args) { 
     if(f != nullptr){ 
      (*f)(std::forward<Args>(args)...); 
     } 
     else 
     { 
      //DO Nothing for void 
     } 
    } 
}; 

//Usage: 
WrapFuncObjVoid<foo> WrapFoo(&gfFoo); 
WrapFoo(); 
WrapFuncObj<bar, int, char*> WrapBar(&gfBar); 
WrapBar(0, "test"); 

、関数ポインタがNULLの場合はnullの場合には、何も返されるべきではないので、非ボイドと、ボイドタイプに別々のテンプレートが必要です。どのようにこの問題を回避し、両方のために十分な1つのテンプレートを作る?

+0

どこかで 'void 'の戻り値型を特殊化することを避ける方法はありません。 –

+0

@SamVarshavchik:そうです。 [C++ではvoidを返すことができます(http://stackoverflow.com/questions/3383090/is-returning-void-valid-code)。 – Cornstalks

+0

もしそれらがコンストラクタにnullを渡すのであれば、ポインタをデフォルトの関数に設定しないのはなぜですか? –

答えて

3

return T();とすることができます(希望する返品タイプはTとする)。これはvoidタイプで動作します。デフォルト以外のコンストラクタを持つ型では機能しません。

#include <iostream> 
#include <utility> 

void foo() { 
    std::cout << "void foo()\n"; 
} 

int bar(int u, char* c_str) { 
    std::cout << "int bar(" << u << ", \"" << c_str << "\")\n"; 
    return u; 
} 

template<typename T> 
class WrapFuncObj; 

template<typename T, typename... Args> 
class WrapFuncObj<T(Args...)> { 
    T (*f)(Args...); 
public: 
    WrapFuncObj(T (*t)(Args...)) { 
     f = t; 
    } 

    T operator()(Args&&... args) { 
     if(f != nullptr) { 
      return (*f)(std::forward<Args>(args)...); 
     } else { 
      return T(); 
     } 
    } 
}; 

int main() { 
    WrapFuncObj<void()> wrap_foo(&foo); 
    wrap_foo(); 

    WrapFuncObj<int(int, char*)> wrap_bar(&bar); 
    wrap_bar(0, "test"); 

    WrapFuncObj<void()> wrap_null(nullptr); 
    wrap_null(); // prints nothing. 
} 

Live demo

私はstd::functionを提案することを義務付けられています。あなたが再作成しようとしているものです(ヌル関数を呼び出して、実際にやりたいことかもしれないデフォルトの型を返すことは許されます)。

+0

ありがとう!それは私が探していたものです。 std :: functionについて読んでいます。しかし、オプションの関数であるため、関数ポインタがnullの場合があり、デフォルト値を返すこともできます。もう一度あなたの助けに感謝します! –

関連する問題