2013-07-30 177 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,你原来的代码一样。那真的是你想要的吗?

相关问题