可変個引数テンプレートを使用してDelegateクラスを実装しようとしているときに、解決できない問題に遭遇しました。
/// --------------------------------------
/// @thanks God
/// Steve Reinalter
/// @author Henri Korpela aka Helixirr
/// --------------------------------------
#include <cstdio>
template<typename>
class Delegate;
template<typename Return, typename Param, typename... ParamsOther>
class Delegate<Return (Param, ParamsOther...)>{
public:
/// Constructors & destructors:
Delegate(void) = default;
Delegate(Delegate const& delegate_) = default;
Delegate(Delegate&& delegate_) = default;
/// Member functions:
Delegate& bind(Return (*function_)(Param, ParamsOther...));
template<class C>
Delegate& bind(C& c_, Return (C::*function_)(Param, ParamsOther...));
/// Member functions (overloaded operators, assignment):
Delegate& operator=(Delegate const& delegate_) = default;
Delegate& operator=(Delegate&& delegate_) = default;
/// Member functions (overloaded operators, function call):
inline Return operator()(Param param_, ParamsOther... params_other_) const;
private:
/// Member data:
Return (*_m_opFunction)(Param, ParamsOther...) = nullptr;
void* _m_opInstance = nullptr;
/// Static member functions:
template<class C, Return (C::*Function)(Param, ParamsOther...)>
static inline Return _wrap_function_member(void* instance_, Param param_, ParamsOther... params_other_);
template<Return (*Function)(Param, ParamsOther...)>
static inline Return _wrap_function_static(void*, Param param_, ParamsOther... params_other_);
};
/// Member functions:
template<typename Return, typename Param, typename... ParamsOther>
Delegate<Return (Param, ParamsOther...)>& Delegate<Return (Param, ParamsOther...)>::bind(Return (*function_)(Param, ParamsOther...)){
_m_opFunction = &_wrap_function_static<decltype(function_)>;
_m_opInstance = nullptr;
return *this;
}
template<typename Return, typename Param, typename... ParamsOther>
template<class C>
Delegate<Return (Param, ParamsOther...)>& Delegate<Return (Param, ParamsOther...)>::bind(C& c_, Return (C::*function_)(Param, ParamsOther...)){
_m_opFunction = &_wrap_function_member<C, decltype(function_)>;
_m_opInstance = &c_;
return *this;
}
/// Member functions (overloaded operators, function call):
template<typename Return, typename Param, typename... ParamsOther>
Return Delegate<Return (Param, ParamsOther...)>::operator()(Param param_, ParamsOther... params_other_) const{
return _m_opFunction(_m_opInstance, param_, params_other_...);
}
/// Static member functions:
template<typename Return, typename Param, typename... ParamsOther>
template<class C, Return (C::*Function)(Param, ParamsOther...)>
Return Delegate<Return (Param, ParamsOther...)>::_wrap_function_member(void* instance_, Param param_, ParamsOther... params_other_){
return (static_cast<C*>(instance_)->*Function)(param_, params_other_...);
}
template<typename Return, typename Param, typename... ParamsOther>
template<Return (*Function)(Param, ParamsOther...)>
Return Delegate<Return (Param, ParamsOther...)>::_wrap_function_static(void*, Param param_, ParamsOther... params_other_){
return (Function)(param_, params_other_...);
}
int f(int i_){
return i_ * 2;
}
int main(void){
Delegate<int (int)> delegate__;
delegate__.bind(&f);
printf("Result: %i\n", delegate__(8));
return 0;
}
これをIdeoneで C++11 コンパイラ ( GCC 4.7.2 ) でコンパイルしようとしましたが、失敗したようです:
prog.cpp: 'Delegate& Delegate::bind(Return (*)(Param, ParamsOther ...)) のインスタンス化で [with Return = int; パラメータ = int; ParamsOther = {}]': prog.cpp:79:23: ここから必要 prog.cpp:45:5: エラー: 関数 '_wrap_function_static' をタイプ 'int (*)(int)' に変換する一致はありません prog.cpp: 39:26: エラー: 候補は: テンプレート static Return Delegate::_wrap_function_static(void*, Param, ParamsOther ...) [with Return (* Function)(Param, ParamsOther ...) = Function; 戻り値 = int; パラメータ = int; ParamsOther = {}] prog.cpp: 'Return Delegate::operator()(Param, ParamsOther ...) のインスタンス化で const [with Return = int; パラメータ = int; ParamsOther = {}]': prog.cpp:80:40: ここから必要 prog.cpp:59:65: エラー: 'void*' から 'int' への無効な変換 [-fpermissive] prog.cpp:59:65 : エラー: 機能する引数が多すぎます
私が理解できることから、decltypeと関数ポインターはこちら
template<typename Return, typename Param, typename... ParamsOther>
Delegate<Return (Param, ParamsOther...)>& Delegate<Return (Param, ParamsOther...)>::bind(Return (*function_)(Param, ParamsOther...)){
_m_opFunction = &_wrap_function_static<decltype(function_)>;
_m_opInstance = nullptr;
return *this;
}
問題を引き起こしているようです。メンバー関数をデリゲートにバインドしようとすると、同じことが起こります。これはなぜですか?私は何を間違っていますか?関数ポインターの型を取得し、その型をテンプレート引数として使用するのはごく自然なことのように思えますが、何らかの理由で、ここでは機能しません。この decltype と関数ポインターのシナリオの何が問題になっていますか?