lambda的模板参数推导

时间:2013-07-30 21:25:24

标签: c++ templates c++11 lambda c++14

如果给定的weak_ptr有效,我正在尝试创建一个执行lambda / std :: function的辅助函数。目前以下代码有效,但不幸的是,它需要我定义模板参数。我正在寻找一种方法来实现自动模板参数推导。

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

理想情况下,我想用通用模板参数std::function <void(ArgumentTypes...)>替换FunctorType,但后来我不确定如何从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...);
        }
    }
}

有没有办法做这样的事情?

3 个答案:

答案 0 :(得分: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中,大部分内容会更容易。

顺便说一句,似乎存在一个基本的设计缺陷:条件转发器应该在.lock()上获取weak_ptr,然后在该锁中执行functor,以便前提条件(资源被保留)适用于functor的整个调用。

当我可以复制weak_ptr的远程状态时,我也不确定为什么要保留对weak_ptr的引用。

在C ++ 14中,您可以返回类似的内容:

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

我相信,decltype内容也会消失,因为函数可以更轻松地推断出它们的返回类型。

答案 1 :(得分: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
  • 的返回类型
  • 一个可变的通用lambda,具有完美转发以调用内部functor

编辑:上面的代码通过引用捕获dependent,就像您的原始代码一样。这真的是你想要的吗?

答案 2 :(得分: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