2013-07-30 32 views
8

私は、指定されたweak_ptrが有効な場合にlambda/std ::関数を実行するヘルパー関数を作成しようとしています。現在、次のコードは機能しますが、残念ながら、テンプレートパラメータを定義する必要があります。私は自動テンプレート引数の控除でこれを行う方法を探しています。ラムダ用のテンプレート引数の控除

template <typename DependentType, typename... ArgumentTypes> 
auto make_dependent(std::weak_ptr<DependentType>& dependent, std::function < void(ArgumentTypes...)> functor) -> decltype(functor) 
{ 
    return [&dependent, functor] (ArgumentTypes... args) 
    { 
     if (!dependent.expired()) { 
      functor(args...); 
     } 
    }; 
}; 

理想的には、私は、一般的なテンプレートパラメータFunctorTypestd::function <void(ArgumentTypes...)>を交換したいのですが、その後、私は私がFunctorTypeから引数を抽出する方法をわかりません。上記のコードは動作しますが、以下のコードは理論的です:

template <typename DependentType, typename FunctorType> 
auto make_dependent_ideal(std::weak_ptr<DependentType>& dependent, FunctorType functor) -> decltype(std::function<return_value(functor)(argument_list(functor))>) 
{ 
    return[&dependent, functor](argument_list(functor) args) 
    { 
     if (!dependent.expired()) { 
      functor(args...); 
     } 
    } 
} 

このような方法はありますか?

+0

'ArgendTypes'の後に' DependentType'を置くと、 'DependentType'が導かれるので' ArgumentTypes'だけを指定するだけです。 – Casey

答えて

5

パラメータから引数を抽出することで問題を解決する最も簡単な方法は、パラメータから引数を抽出しないことです。

template<typename F, typename C> 
struct conditional_forwarder { 
    F func; 
    C cond; 
    template<typename Fin, typename Cin> 
    conditional_forwarder(Fin&& f, Cin&& c): 
    func(std::forward<Fin>(f)), cond(std::forward<Cin>(c)) {} 
    template<typename... Args> 
    void operator()(Args&&... args) const { 
    if (cond()) 
     func(std::forward<Args>(args)...); 
    } 
}; 
template<typename F, typename C> 
conditional_forwarder< typename std::decay<F>::type, typename std::decay<C>::type > 
make_conditional_forwarder(F&& f, C&& c) { 
    return {std::forward<F>(f), std::forward<C>(c)}; 
} 
// todo: make_dependent_test 

template <typename DependentType, typename FunctorType> 
auto make_dependent_ideal(std::weak_ptr<DependentType>& dependent, FunctorType functor) 
    -> decltype(make_conditional_forwarder(make_dependent_test(dependent), functor)) 
{ 
    return make_conditional_forwarder(make_dependent_test(dependent), functor); 
} 

これの多くはC++で容易になります。

さておき、基本的な設計上の欠陥があるように思わ通り:(リソースが保持されていることを)前提条件が成立するように、条件付きフォワーダは、おそらく、weak_ptr.lock()をAQUIRE、次にそのロック内functorを実行する必要がありますfunctorの全体の呼び出し。

weak_ptrのリモート状態をコピーできる理由を、weak_ptrへの参照が保持されている理由もわかりません。 C++ 14では

、あなたのような何かを返すことができます:私は信じている

return [=](auto&&... args) mutable { 
} 

を、そしてdecltypeものも機能をより簡単に自分の戻り値の型を推論することができ、ほとんどのように消えます。

+0

'[=](auto && ... args)mutable {}'はどういう意味ですか?パラメータの部分と '変更可能な部分の両方が私を混乱させます。 –

+0

@ LB--パラメータは暗黙的に型付けされていると私は信じている。 'mutable'は生成されたラムダ上の' operator() 'がそのキャプチャされた変数を変更できることを意味するラムダのC++ 11修飾子です。 – Yakk

1

プロキシ特性クラスを使用して、単一のテンプレートパラメータとは別に戻り値の型と引数を抽出できます。 Traitクラスは静的関数dependent_funcを使用して、返すラムダを作成します。このように、テンプレート引数の解析についての詳細情報については

template <typename DependentType, typename FunctorType> 
struct Trait {}; 

template <typename DependentType, typename ReturnType, typename... ArgumentTypes> 
struct Trait<DependentType, std::function<ReturnType(ArgumentTypes...)>> { 
    static std::function<ReturnType(ArgumentTypes...)> dependent_func(const std::weak_ptr<DependentType>& dependent, std::function<ReturnType(ArgumentTypes...)>& functor) { 
     return [&dependent, &functor] (ArgumentTypes... args) { 
      if (!dependent.expired()) { 
       return functor(args...); 
      } 
     }; 
    } 
}; 

template <typename DependentType, typename FunctorType> 
auto make_dependent_ideal(std::weak_ptr<DependentType>& dependent, FunctorType& functor) -> decltype(Trait<DependentType, FunctorType>::dependent_func(dependent, functor)) { 
    return Trait<DependentType, FunctorType>::dependent_func(dependent, functor); 
} 

、この質問を見て:C++ parsing function-type template argument

2

をここに私はC++ 14であなたの問題を解決したい方法は次のとおりです。

template<typename DependentType, typename FunctorType> 
auto make_dependent(std::weak_ptr<DependentType> &dependent, FunctorType functor) { 
    return [&dependent, functor](auto &&...args) { 
    if (!dependent.expired()) 
     functor(std::forward<decltype(args)>(args)...); 
    } 
} 

Iここでは2つのC++ 14の機能を使用しています:

  • 返還タイプmake_dependent
functorインナーEDIT呼び出すのに最適な転送と可変引数ジェネリックラムダ:あなたの元のコードが行ったように上記のコードは、参照することにより dependentをキャプチャします。それは本当にあなたが望むものですか?

関連する問題