2013-07-30 79 views
8

我試圖做一個幫助函數,如果給定的weak_ptr是有效的,當調用時執行lambda/std :: function。目前下面的代碼有效,但不幸的是,它需要我定義模板參數。我正在尋找一種方法來做到這一點與自動模板參數扣除。lambda的模板參數演繹

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...); 
     } 
    }; 
}; 

理想情況下,我想用一個通用模板參數FunctorType更換std::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

如果你在'ArgumentTypes'後面加上'DependentType',你只需要指定'ArgumentTypes',因爲'DependentType'是可以被推斷的。 – 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++ 14中。

順便說一句,似乎有一個基本的設計缺陷:條件轉發也許應該在weak_ptr AQUIRE一個.lock(),然後該鎖內執行functor,這樣的前提(即資源被持有)適用於整個電話號碼爲functor

我也不清楚爲什麼你拿着一個weak_ptr,當weak_ptr的遠程狀態可以被複制的參考。

在C++ 14,你可以返回類似:

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

我相信,和decltype東西也消失大多是因爲功能可以更容易地推斷出他們的返回類型。

+0

'[= =(auto && ... args)mutable {}'是什麼意思?參數部分和「可變」部分都讓我感到困惑。 –

+0

@ LB--參數是隱式類型的,我相信C++ 14的一個特性。 'mutable'是一個用於lambda的C++ 11修飾符,這意味着生成的lambda上的'operator()'可以修改其捕獲的變量。 – Yakk

1

您可以使用代理特徵類從單個模板參數中分別提取返回類型和參數。 Trait類使用靜態函數dependent_func來創建要返回的lambda。

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)...); 
    } 
} 

我這裏使用兩個C++ 14功能:

  • 扣除退貨類型爲make_dependent
  • 完美轉發的可變參數的通用拉姆達調用內functor

編輯:上面的代碼參照捕捉dependent,你原來的代碼一樣。那真的是你想要的嗎?

相關問題